E5Network/E5SslInfoWidget.py

changeset 2432
b1a2f9054b28
parent 2359
ef81d2d0a031
child 2525
8b507a9a2d40
child 2537
0ff250733d45
equal deleted inserted replaced
2430:fd7fa26076d2 2432:b1a2f9054b28
2 2
3 # Copyright (c) 2010 - 2013 Detlev Offenbach <detlev@die-offenbachs.de> 3 # Copyright (c) 2010 - 2013 Detlev Offenbach <detlev@die-offenbachs.de>
4 # 4 #
5 5
6 """ 6 """
7 Module implementing a widget to show SSL certificate infos. 7 Module implementing a widget to show SSL information.
8 """ 8 """
9 9
10 from PyQt4.QtCore import QCryptographicHash, QDateTime, qVersion 10 from PyQt4.QtCore import qVersion, Qt, QUrl, QPoint
11 from PyQt4.QtGui import QWidget 11 from PyQt4.QtGui import QMenu, QGridLayout, QLabel, QSizePolicy
12 from PyQt4.QtNetwork import QSslCertificate 12 from PyQt4.QtNetwork import QSsl, QSslConfiguration, QSslCertificate
13 13
14 from .Ui_E5SslInfoWidget import Ui_E5SslInfoWidget 14 import UI.PixmapCache
15
16 import Utilities 15 import Utilities
17 16
18 17
19 class E5SslInfoWidget(QWidget, Ui_E5SslInfoWidget): 18 class E5SslInfoWidget(QMenu):
20 """ 19 """
21 Class implementing a widget to show SSL certificate infos. 20 Class implementing a widget to show SSL certificate infos.
22 """ 21 """
23 def __init__(self, parent=None): 22 def __init__(self, url, configuration, parent=None):
24 """ 23 """
25 Constructor 24 Constructor
26 25
26 @param url URL to show SSL info for (QUrl)
27 @param configuration SSL configuration (QSslConfiguration)
27 @param parent reference to the parent widget (QWidget) 28 @param parent reference to the parent widget (QWidget)
28 """ 29 """
29 super().__init__(parent) 30 super().__init__(parent)
30 self.setupUi(self)
31 31
32 def showCertificate(self, certificate): 32 self.__url = QUrl(url)
33 self.__configuration = QSslConfiguration(configuration)
34
35 self.setAttribute(Qt.WA_DeleteOnClose)
36 self.setMinimumWidth(400)
37
38 certList = self.__configuration.peerCertificateChain()
39 if certList:
40 cert = certList[0]
41 else:
42 cert = QSslCertificate()
43
44 layout = QGridLayout(self)
45 rows = 0
46
47 ##########################################
48 ## Identity Information
49 ##########################################
50 imageLabel = QLabel(self)
51 layout.addWidget(imageLabel, rows, 0, Qt.AlignCenter)
52
53 label = QLabel(self)
54 label.setWordWrap(True)
55 label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
56 label.setText(self.trUtf8("Identity"))
57 font = label.font()
58 font.setBold(True)
59 label.setFont(font)
60 layout.addWidget(label, rows, 1)
61 rows += 1
62
63 label = QLabel(self)
64 label.setWordWrap(True)
65 if cert.isNull():
66 label.setText(
67 self.trUtf8("Warning: this site is NOT carrying a certificate."))
68 imageLabel.setPixmap(UI.PixmapCache.getPixmap("securityLow32.png"))
69 else:
70 if qVersion() >= "5.0.0":
71 valid = not cert.isBlacklisted()
72 else:
73 valid = cert.isValid()
74 if valid:
75 if qVersion() >= "5.0.0":
76 txt = ", ".join(cert.issuerInfo(QSslCertificate.CommonName))
77 else:
78 txt = cert.issuerInfo(QSslCertificate.CommonName)
79 label.setText(self.trUtf8("The certificate for this site is valid"
80 " and has been verified by:\n{0}").format(
81 Utilities.decodeString(txt)))
82 imageLabel.setPixmap(UI.PixmapCache.getPixmap("securityHigh32.png"))
83 else:
84 label.setText(self.trUtf8("The certificate for this site is NOT valid."))
85 imageLabel.setPixmap(UI.PixmapCache.getPixmap("securityLow32.png"))
86 layout.addWidget(label, rows, 1)
87 rows += 1
88
89 label = QLabel(self)
90 label.setWordWrap(True)
91 label.setText('<a href="moresslinfos">' +
92 self.trUtf8("Certificate Information") + "</a>")
93 label.linkActivated.connect(self.__showCertificateInfos)
94 layout.addWidget(label, rows, 1)
95 rows += 1
96
97 ##########################################
98 ## Identity Information
99 ##########################################
100 imageLabel = QLabel(self)
101 layout.addWidget(imageLabel, rows, 0, Qt.AlignCenter)
102
103 label = QLabel(self)
104 label.setWordWrap(True)
105 label.setText(self.trUtf8("Encryption"))
106 font = label.font()
107 font.setBold(True)
108 label.setFont(font)
109 layout.addWidget(label, rows, 1)
110 rows += 1
111
112 cipher = self.__configuration.sessionCipher()
113 if cipher.isNull():
114 label = QLabel(self)
115 label.setWordWrap(True)
116 label.setText(self.trUtf8(
117 'Your connection to "{0}" is NOT encrypted.\n').format(
118 self.__url.host()))
119 layout.addWidget(label, rows, 1)
120 imageLabel.setPixmap(UI.PixmapCache.getPixmap("securityLow32.png"))
121 rows += 1
122 else:
123 label = QLabel(self)
124 label.setWordWrap(True)
125 label.setText(self.trUtf8(
126 'Your connection to "{0}" is encrypted.').format(
127 self.__url.host()))
128 layout.addWidget(label, rows, 1)
129
130 proto = cipher.protocol()
131 if proto == QSsl.SslV3:
132 sslVersion = "SSL 3.0"
133 imageLabel.setPixmap(UI.PixmapCache.getPixmap("securityHigh32.png"))
134 elif proto == QSsl.TlsV1:
135 sslVersion = "TLS 1.0"
136 imageLabel.setPixmap(UI.PixmapCache.getPixmap("securityHigh32.png"))
137 elif proto == QSsl.SslV2:
138 sslVersion = "SSL 2.0"
139 imageLabel.setPixmap(UI.PixmapCache.getPixmap("securityLow32.png"))
140 else:
141 sslVersion = self.trUtf8("unknown")
142 imageLabel.setPixmap(UI.PixmapCache.getPixmap("securityLow32.png"))
143 rows += 1
144
145 label = QLabel(self)
146 label.setWordWrap(True)
147 label.setText(self.trUtf8("It uses protocol: {0}").format(sslVersion))
148 layout.addWidget(label, rows, 1)
149 rows += 1
150
151 label = QLabel(self)
152 label.setWordWrap(True)
153 label.setText(self.trUtf8(
154 "It is encrypted using {0} at {1} bits, "
155 "with {2} for message authentication and "
156 "{3} as key exchange mechanism.\n\n").format(
157 cipher.encryptionMethod(),
158 cipher.usedBits(),
159 cipher.authenticationMethod(),
160 cipher.keyExchangeMethod()))
161 layout.addWidget(label, rows, 1)
162 rows += 1
163
164 def showAt(self, pos):
33 """ 165 """
34 Public method to show the SSL certificate information. 166 Public method to show the widget.
35 167
36 @param certificate reference to the SSL certificate (QSslCertificate) 168 @param pos position to show at (QPoint)
37 """ 169 """
38 self.blacklistedLabel.setVisible(False) 170 self.adjustSize()
39 self.blacklistedLabel.setStyleSheet( 171 p = QPoint(pos.x() - self.width(), pos.y() + 10)
40 "QLabel { color : white; background-color : red; }") 172 self.move(p)
41 self.expiredLabel.setVisible(False) 173 self.show()
42 self.expiredLabel.setStyleSheet(
43 "QLabel { color : white; background-color : red; }")
44
45 if qVersion() >= "5.0.0":
46 self.subjectCommonNameLabel.setText(self.__certificateString(
47 ", ".join(certificate.subjectInfo(QSslCertificate.CommonName))))
48 self.subjectOrganizationLabel.setText(self.__certificateString(
49 ", ".join(certificate.subjectInfo(QSslCertificate.Organization))))
50 self.subjectOrganizationalUnitLabel.setText(self.__certificateString(
51 ", ".join(
52 certificate.subjectInfo(QSslCertificate.OrganizationalUnitName))))
53 self.issuerCommonNameLabel.setText(self.__certificateString(
54 ", ".join(certificate.issuerInfo(QSslCertificate.CommonName))))
55 self.issuerOrganizationLabel.setText(self.__certificateString(
56 ", ".join(certificate.issuerInfo(QSslCertificate.Organization))))
57 self.issuerOrganizationalUnitLabel.setText(self.__certificateString(
58 ", ".join(certificate.issuerInfo(QSslCertificate.OrganizationalUnitName))))
59 else:
60 self.subjectCommonNameLabel.setText(self.__certificateString(
61 certificate.subjectInfo(QSslCertificate.CommonName)))
62 self.subjectOrganizationLabel.setText(self.__certificateString(
63 certificate.subjectInfo(QSslCertificate.Organization)))
64 self.subjectOrganizationalUnitLabel.setText(self.__certificateString(
65 certificate.subjectInfo(QSslCertificate.OrganizationalUnitName)))
66 self.issuerCommonNameLabel.setText(self.__certificateString(
67 certificate.issuerInfo(QSslCertificate.CommonName)))
68 self.issuerOrganizationLabel.setText(self.__certificateString(
69 certificate.issuerInfo(QSslCertificate.Organization)))
70 self.issuerOrganizationalUnitLabel.setText(self.__certificateString(
71 certificate.issuerInfo(QSslCertificate.OrganizationalUnitName)))
72 self.serialNumberLabel.setText(self.__serialNumber(certificate))
73 self.effectiveLabel.setText(
74 certificate.effectiveDate().toString("yyyy-MM-dd"))
75 self.expiresLabel.setText(
76 certificate.expiryDate().toString("yyyy-MM-dd"))
77 self.sha1Label.setText(self.__formatHexString(
78 str(certificate.digest(QCryptographicHash.Sha1).toHex(), encoding="ascii")))
79 self.md5Label.setText(self.__formatHexString(
80 str(certificate.digest(QCryptographicHash.Md5).toHex(), encoding="ascii")))
81
82 if (qVersion() >= "5.0.0" and certificate.isBlacklisted()) or \
83 (qVersion() < "5.0.0" and not certificate.isValid()):
84 # something is wrong; indicate it to the user
85 if self.__hasExpired(certificate.effectiveDate(), certificate.expiryDate()):
86 self.expiredLabel.setVisible(True)
87 else:
88 self.blacklistedLabel.setVisible(True)
89 174
90 def __certificateString(self, txt): 175 def __showCertificateInfos(self):
91 """ 176 """
92 Private method to prepare some text for display. 177 Private slot to show certificate information.
93
94 @param txt text to be displayed (string)
95 @return prepared text (string)
96 """ 178 """
97 if txt is None or txt == "": 179 from .E5SslCertificatesInfoDialog import E5SslCertificatesInfoDialog
98 return self.trUtf8("<not part of the certificate>") 180 dlg = E5SslCertificatesInfoDialog(self.__configuration.peerCertificateChain())
99 181 dlg.exec_()
100 return Utilities.decodeString(txt)
101 182
102 def __serialNumber(self, cert): 183 def accept(self):
103 """ 184 """
104 Private slot to format the certificate serial number. 185 Public method to accept the widget.
105
106 @param cert reference to the SSL certificate (QSslCertificate)
107 @return formated serial number (string)
108 """ 186 """
109 serial = cert.serialNumber() 187 self.close()
110 if serial == "":
111 return self.trUtf8("<not part of the certificate>")
112
113 if ':' in serial:
114 return str(serial, encoding="ascii").upper()
115 else:
116 hexString = hex(int(serial))[2:]
117 return self.__formatHexString(hexString)
118
119 def __formatHexString(self, hexString):
120 """
121 Private method to format a hex string for display.
122
123 @param hexString hex string to be formatted (string)
124 @return formatted string (string)
125 """
126 hexString = hexString.upper()
127
128 if len(hexString) % 2 == 1:
129 hexString = '0' + hexString
130
131 hexList = []
132 while hexString:
133 hexList.append(hexString[:2])
134 hexString = hexString[2:]
135
136 return ':'.join(hexList)
137
138 def __hasExpired(self, effectiveDate, expiryDate):
139 """
140 Private method to check for a certificate expiration.
141
142 @param effectiveDate date the certificate becomes effective (QDateTime)
143 @param expiryDate date the certificate expires (QDateTime)
144 @return flag indicating the expiration status (boolean)
145 """
146 now = QDateTime.currentDateTime()
147
148 return now < effectiveDate or now >= expiryDate

eric ide

mercurial