def importCertificateDialog(repView): """ Let the user import a certificate. First brings up a file selection dialog, then asks for trust settings for the certificate being imported. """ certificate = None app = wx.GetApp() res = Util.showFileDialog(app.mainFrame, _(u"Choose a certificate to import"), u"", u"", _(u"PEM files|*.pem;*.crt|All files (*.*)|*.*"), wx.OPEN) (cmd, dir, filename) = res if cmd == wx.ID_OK: # dir and filename are unicode path = os.path.join(dir, filename) try: x509 = X509.load_cert(path) fprint = utils.fingerprint(x509) purpose = certificatePurpose(x509) # Note: the order of choices must match the selections code below choices = [_(u"Trust this certificate.")] if purpose & constants.PURPOSE_CA: choices += [ _(u"Trust this certificate to sign site certificates.") ] dlg = dialogs.ImportCertificateDialog(app.mainFrame, purpose, fprint, x509, choices) trust = constants.TRUST_NONE if dlg.ShowModal() == wx.ID_OK: selections = dlg.GetSelections() # Note: this code must match the choices above for sel in selections: if sel == 0: trust |= constants.TRUST_AUTHENTICITY if sel == 1: trust |= constants.TRUST_SERVER certificate = importCertificate(x509, fprint, trust, repView) dlg.Destroy() except utils.CertificateException, e: wx.MessageBox(e.__unicode__(), messages.ERROR, parent=wx.GetApp().mainFrame) except Exception, e: log.exception(e) wx.MessageBox(_( u"Could not add certificate from: %(path)s\nCheck the path and try again." ) % {'path': path}, messages.ERROR, parent=wx.GetApp().mainFrame)
def importCertificateDialog(repView): """ Let the user import a certificate. First brings up a file selection dialog, then asks for trust settings for the certificate being imported. """ certificate = None app = wx.GetApp() res = Util.showFileDialog(app.mainFrame, _(u"Choose a certificate to import"), u"", u"", _(u"PEM files|*.pem;*.crt|All files (*.*)|*.*"), wx.OPEN) (cmd, dir, filename) = res if cmd == wx.ID_OK: # dir and filename are unicode path = os.path.join(dir, filename) try: x509 = X509.load_cert(path) fprint = utils.fingerprint(x509) purpose = certificatePurpose(x509) # Note: the order of choices must match the selections code below choices = [_(u"Trust this certificate.")] if purpose & constants.PURPOSE_CA: choices += [_(u"Trust this certificate to sign site certificates.")] dlg = dialogs.ImportCertificateDialog(app.mainFrame, purpose, fprint, x509, choices) trust = constants.TRUST_NONE if dlg.ShowModal() == wx.ID_OK: selections = dlg.GetSelections() # Note: this code must match the choices above for sel in selections: if sel == 0: trust |= constants.TRUST_AUTHENTICITY if sel == 1: trust |= constants.TRUST_SERVER certificate = importCertificate(x509, fprint, trust, repView) dlg.Destroy() except utils.CertificateException, e: wx.MessageBox (e.__unicode__(), messages.ERROR, parent=wx.GetApp().mainFrame) except Exception, e: log.exception(e) wx.MessageBox (_(u"Could not add certificate from: %(path)s\nCheck the path and try again.") % {'path': path}, messages.ERROR, parent=wx.GetApp().mainFrame)
def askTrustServerCertificate(host, pem, reconnect): """ Ask user if they would like to trust the certificate that was returned by the server. This will only happen if the certificate is not already trusted, either by trust chain or explicitly. @note: If you want to reconnect on background thread, pass in a dummy reconnect and reconnect manually after receiving True. @param host: The host we think we are connected with. @param pem: The certificate in PEM format. @param reconnect: The reconnect callback that will be called if the user chooses to trust the certificate. @return: True if user chose to trust, False otherwise. """ from osaf.framework.certstore import dialogs, certificate global trusted_until_shutdown_site_certs repositoryView = wx.GetApp().UIRepositoryView x509 = X509.load_cert_string(pem) untrustedCertificate = certificate.findCertificate(repositoryView, pem) dlg = dialogs.TrustServerCertificateDialog(wx.GetApp().mainFrame, x509, host, untrustedCertificate) try: if dlg.ShowModal() == wx.ID_OK: selection = dlg.GetSelection() if selection == 0: trusted_until_shutdown_site_certs += [pem] else: if untrustedCertificate is not None: untrustedCertificate.trust |= constants.TRUST_AUTHENTICITY else: fingerprint = utils.fingerprint(x509) certificate.importCertificate(x509, fingerprint, constants.TRUST_AUTHENTICITY, repositoryView) # In either case here (a known, untrusted cert, or a # completely untrusted cert), we have made a change # and we need to commit so other views can see it. repositoryView.commit() reconnect() return True finally: dlg.Destroy() return False
def testCertificateCache(self): pemRoot = '''-----BEGIN CERTIFICATE----- MIIDpzCCAxCgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBmjELMAkGA1UEBhMCVVMx CzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRowGAYDVQQKExFv c2Fmb3VuZGF0aW9uLm9yZzELMAkGA1UECxMCQ0ExEDAOBgNVBAMTB09TQUYgQ0Ex KzApBgkqhkiG9w0BCQEWHGhvc3RtYXN0ZXJAb3NhZm91bmRhdGlvbi5vcmcwHhcN MDQwNjAyMjEzNTIzWhcNMjkwNTI3MjEzNTIzWjCBmjELMAkGA1UEBhMCVVMxCzAJ BgNVBAgTAkNBMRYwFAYDVQQHEw1TYW4gRnJhbmNpc2NvMRowGAYDVQQKExFvc2Fm b3VuZGF0aW9uLm9yZzELMAkGA1UECxMCQ0ExEDAOBgNVBAMTB09TQUYgQ0ExKzAp BgkqhkiG9w0BCQEWHGhvc3RtYXN0ZXJAb3NhZm91bmRhdGlvbi5vcmcwgZ8wDQYJ KoZIhvcNAQEBBQADgY0AMIGJAoGBAMvKQY9ElPz4UOhYwKPhbHpSzxxGXxQHiOGu QDV9HuTaTD53cs4xhTau5nLrbqR6qkOpaxgq4+xGZGXwwdrl6vABXGamBAIS8U+C IoxMZmdi1zNCHpALjrUOr5zG+l5lbxKMzzfbBgz0EvnxdyUW3JzWlFA7gtKwNeq9 8BbIVNIRAgMBAAGjgfowgfcwHQYDVR0OBBYEFFAUmTv7d1YAmmssTPTcaE3FWgdL MIHHBgNVHSMEgb8wgbyAFFAUmTv7d1YAmmssTPTcaE3FWgdLoYGgpIGdMIGaMQsw CQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDVNhbiBGcmFuY2lzY28x GjAYBgNVBAoTEW9zYWZvdW5kYXRpb24ub3JnMQswCQYDVQQLEwJDQTEQMA4GA1UE AxMHT1NBRiBDQTErMCkGCSqGSIb3DQEJARYcaG9zdG1hc3RlckBvc2Fmb3VuZGF0 aW9uLm9yZ4IBADAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBAUAA4GBAAdPk2l4 bQBw41mQvTLGFVUx89oEqmlW8fMh06/PhNyKPvA+Ip/HL4fl71A8aGYINA2KGQeE Mi6jbcmKpkTked0C7KzayFkggv/SZtmeibzOjQJbO5WQCRgYuF9t7Rijk7oiAt3U 3rOIG1GsNPeKaSKyc+Bpqd9phY+fPNsZf8b4 -----END CERTIFICATE-----''' self.assert_(ssl.certificateCache == [], 'cache should start empty') ssl.getContext(self.view) # set cache self.assert_(ssl.certificateCache != [], 'cache should have an entry after getting a context') x509 = X509.load_cert_string(pemRoot) fingerprint = utils.fingerprint(x509) cert = certificate.importCertificate(x509, fingerprint, constants.TRUST_AUTHENTICITY | constants.TRUST_SERVER, self.view) self.assert_(ssl.certificateCache == [], 'cache should have been cleared after adding a cert') ssl.getContext(self.view) # set cache cert.trust = 0 self.assert_(ssl.certificateCache == [], 'cache should have been cleared after changing cert.trust attribute') ssl.getContext(self.view) # set cache del cert.trust self.assert_(ssl.certificateCache == [], 'cache should have been cleared after deleting cert.trust attribute') ssl.getContext(self.view) # set cache cert.delete() self.assert_(ssl.certificateCache == [], 'cache should have been cleared after removing a cert')
def _importAndFind(self, pem, trust): x509 = X509.load_cert_string(pem) fingerprint = utils.fingerprint(x509) certificate.importCertificate(x509, fingerprint, trust, self.view) view = self.view matchingCerts = FilteredCollection( 'fpCertQuery' + fingerprint, itsView=view, source=utils.getExtent(certificate.Certificate, view, exact=True), filterExpression=u"view.findValue(uuid, 'fingerprint') == '%s'" % fingerprint, filterAttributes=['fingerprint']) self.assert_(len(matchingCerts) == 1) return iter(matchingCerts).next()
def _importAndFind(self, pem, trust): x509 = X509.load_cert_string(pem) fingerprint = utils.fingerprint(x509) certificate.importCertificate(x509, fingerprint, trust, self.view) view = self.view matchingCerts = FilteredCollection('fpCertQuery' + fingerprint, itsView=view, source=utils.getExtent(certificate.Certificate, view, exact=True), filterExpression=u"view.findValue(uuid, 'fingerprint') == '%s'" % fingerprint, filterAttributes=['fingerprint']) self.assert_(len(matchingCerts) == 1) return iter(matchingCerts).next()
def loadCerts(parcel, moduleName, filename=u'cacert.pem'): # Load cacert.pem into the repository import os, sys import logging from M2Crypto import X509 log = logging.getLogger(__name__) if isinstance(filename, unicode): filename = filename.encode('utf8') chop = -1 cert = schema.ns('osaf.framework.certstore', parcel) lobType = schema.itemFor(schema.Lob, parcel.itsView) from osaf.framework.certstore import utils, constants lastLine = '' pem = [] certificates = 0 itsName = None for line in open( os.path.join( os.path.dirname(sys.modules[moduleName].__file__),filename ), 'rU' ): if line[:3] == '===': itsName = lastLine itsName = itsName[:chop] elif line[:chop] == '-----BEGIN CERTIFICATE-----': pem = [line] elif line[:chop] == '-----END CERTIFICATE-----': pem.append(line[:chop]) x509 = X509.load_cert_string(''.join(pem)) if itsName is not None: commonName = itsName itsName = itsName.replace('/', '_') else: commonName = x509.get_subject().commonName or '' if not x509.verify(): log.warn('Skipping certificate, does not verify: %s' % \ (commonName)) #print x509.as_text() continue try: trust = constants.TRUST_AUTHENTICITY | constants.TRUST_SERVER purpose = cert.certificatePurpose(x509) if not (purpose & constants.PURPOSE_CA): trust &= ~constants.TRUST_SERVER log.warn('Importing non-root certificate: %s' % \ (commonName)) except utils.CertificateException: log.warn('Could not determine certificate type, assuming "%s": %s' % \ (constants.PURPOSE_CA, commonName)) purpose = constants.PURPOSE_CA #print x509.as_text() #XXX [i18n] Can a commonName contain non-ascii characters? cert.Certificate.update(parcel, itsName, displayName = unicode(commonName), purpose=purpose, trust=trust, fingerprintAlgorithm='sha1', fingerprint=utils.fingerprint(x509), pem=lobType.makeValue(''.join(pem)), asText=lobType.makeValue(x509.as_text()), ) pem = [] certificates += 1 itsName = None elif pem: pem.append(line) lastLine = line log.info( 'Imported %d certificates from %s in %s', certificates, filename, moduleName )
def __init__(self, parent, x509, host, err, size=wx.DefaultSize, pos=wx.DefaultPosition, style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER): """ Initialize dialog. @param x509: The certificate the site returned. @param host: The host we think we are connected with. @param err: The verification error code """ # Instead of calling wx.Dialog.__init__ we precreate the dialog # so we can set an extra style that must be set before # creation, and then we create the GUI dialog using the Create # method. pre = wx.PreDialog() pre.Create(parent, -1, _(u'Ignore SSL error?'), pos, size, style) # This next step is the most important, it turns this Python # object into the real wrapper of the dialog (instead of pre) # as far as the wxPython extension is concerned. self.this = pre.this # Now continue with the normal construction of the dialog # contents sizer = wx.BoxSizer(wx.VERTICAL) # Static text try: err.upper() errString = err except AttributeError: errString = errors.getCertificateVerifyErrorString(err) message = _(u'There was an error with this SSL connection.\nHost: %(host)s.\nThe error was: %(sslError)s.\nIgnoring this error may be dangerous!\nSHA1 fingerprint: %(fingerprint)s') % \ {'host': host, 'sslError': errString, 'fingerprint': utils.fingerprint(x509)} label = wx.StaticText(self, -1, message) sizer.Add(label, 0, wx.ALIGN_LEFT|wx.ALL, 5) # multiline readonly edit control # XXX [i18n] This cannot be localized. Split into separate fields # XXX [i18n] like the certificate detail view. text = wx.TextCtrl(self, -1, x509.as_text(), wx.DefaultPosition, [400,-1], style=wx.TE_MULTILINE|wx.TE_READONLY) sizer.Add(text, 1, wx.GROW|wx.ALIGN_CENTRE|wx.ALL, 5) # OK, Cancel buttons box = wx.BoxSizer(wx.HORIZONTAL) btn = wx.Button(self, wx.ID_OK, _(u'Ignore Error')) box.Add(btn, 0, wx.ALIGN_RIGHT|wx.ALL, 5) btn = wx.Button(self, wx.ID_CANCEL, _(u'Disconnect')) btn.SetDefault() box.Add(btn, 0, wx.ALIGN_RIGHT|wx.ALL, 5) btn.SetFocus() sizer.Add(box, 0, wx.ALIGN_RIGHT|wx.ALL, 5) self.SetSizer(sizer) self.SetAutoLayout(True) sizer.Fit(self) self.CenterOnScreen()
def __init__(self, parent, x509, host, storedUntrusted, size=wx.DefaultSize, pos=wx.DefaultPosition, style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER): """ Initialize dialog. @param x509: The certificate the site returned. @param host: The host we think we are connected with. @param storedUntrusted: The certificate (if any) that is already stored in the repository but is not trusted. """ # Instead of calling wx.Dialog.__init__ we precreate the dialog # so we can set an extra style that must be set before # creation, and then we create the GUI dialog using the Create # method. pre = wx.PreDialog() pre.Create(parent, -1, _(u'Trust site certificate?'), pos, size, style) # This next step is the most important, it turns this Python # object into the real wrapper of the dialog (instead of pre) # as far as the wxPython extension is concerned. self.this = pre.this # Now continue with the normal construction of the dialog # contents sizer = wx.BoxSizer(wx.VERTICAL) # Static text if storedUntrusted is None: message = _(u'Host: %(host)s.\nDo you want to trust this certificate?\nSHA1 fingerprint: %(fingerprint)s') % \ {'host': host, 'fingerprint': utils.fingerprint(x509)} else: message = _(u'Host: %(host)s.\nThis certificate is already known but not trusted.\nDo you want to trust this certificate now?\nSHA1 fingerprint: %(fingerprint)s') % \ {'host': host, 'fingerprint': utils.fingerprint(x509)} label = wx.StaticText(self, -1, message) sizer.Add(label, 0, wx.ALIGN_LEFT|wx.ALL, 5) # multiline readonly edit control # XXX [i18n] This cannot be localized. Split into separate fields # XXX [i18n] like the certificate detail view. text = wx.TextCtrl(self, -1, x509.as_text(), wx.DefaultPosition, [400,-1], style=wx.TE_MULTILINE|wx.TE_READONLY) sizer.Add(text, 1, wx.GROW|wx.ALIGN_CENTRE|wx.ALL, 5) # radio radiobox = wx.BoxSizer(wx.VERTICAL) first = True rbs = [] choices=[_(u'Trust the authenticity of this certificate &until you quit Chandler.'), _(u'Trust the authenticity of this certificate &permanently.')] for choice in choices: if first: style = wx.ALIGN_LEFT|wx.RB_GROUP else: style = wx.ALIGN_LEFT rb = wx.RadioButton(self, -1, choice, wx.DefaultPosition, wx.DefaultSize, style) rbs += [rb] radiobox.Add(rb, 1, wx.ALIGN_LEFT|wx.ALL, 5) if first: rb.SetValue(True) first = False sizer.Add(radiobox, 0, wx.ALIGN_LEFT|wx.ALL, 5) # OK, Cancel buttons box = wx.BoxSizer(wx.HORIZONTAL) btn = wx.Button(self, wx.ID_OK) box.Add(btn, 0, wx.ALIGN_RIGHT|wx.ALL, 5) btn = wx.Button(self, wx.ID_CANCEL) btn.SetDefault() box.Add(btn, 0, wx.ALIGN_RIGHT|wx.ALL, 5) btn.SetFocus() sizer.Add(box, 0, wx.ALIGN_RIGHT|wx.ALL, 5) self.SetSizer(sizer) self.SetAutoLayout(True) sizer.Fit(self) self.CenterOnScreen() self.rbs = rbs