summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2015-05-30 17:52:44 +0200
committerPeter Wu <peter@lekensteyn.nl>2015-05-30 17:52:44 +0200
commit9bb65586f6f8e4a2ba2da23feb4ee8b224e45491 (patch)
treed39f6e8861880f08012ca2d8584fb55e34bc3e1e
parentb367416f1b65564675a3a9093137cbd20291b5c3 (diff)
downloadscripts-9bb65586f6f8e4a2ba2da23feb4ee8b224e45491.tar.gz
startcom-sha2.py: utility to fix broken SHA256 intermediates
Replaces intermediate certificates (PEM format) by other certificates. Beware of line endings! Supports both Python 2.7 and 3.
-rwxr-xr-xstartcom-sha2.py382
1 files changed, 382 insertions, 0 deletions
diff --git a/startcom-sha2.py b/startcom-sha2.py
new file mode 100755
index 0000000..ea09710
--- /dev/null
+++ b/startcom-sha2.py
@@ -0,0 +1,382 @@
+#!/usr/bin/env python
+'''
+This program scans for StartCom's intermediate SHA256 certificate files which
+have known compatibility issues with some Windows clients due to a cached SHA-1
+certificate. It can also fix these certificate files.
+
+Note that the new certificates **expire on 24 October 2017** while the
+recommended (but problematic certs) expire on **14 October 2022**. Supported
+intermediate CAs with their old and new serial number.
+
+ StartCom Class 1 Primary Intermediate Server CA
+ 0x17153d9eab3fbf -> 0x19
+ StartCom Class 2 Primary Intermediate Server CA
+ 0x1cab36472d9c51 -> 0x1b
+ StartCom Class 3 Primary Intermediate Server CA
+ 0x15a85b7110adcf -> 0x1d
+
+More details are available at
+https://forum.startcom.org/viewtopic.php?p=21826#p21826
+'''
+
+class1 = (
+# https://www.startssl.com/certs/class1/sha2/pem/sub.class1.server.sha2.ca.pem
+b'''
+-----BEGIN CERTIFICATE-----''' + b'''
+MIIF2TCCA8GgAwIBAgIHFxU9nqs/vzANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQG
+EwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERp
+Z2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2Vy
+dGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDcxMDE0MjA1NDE3WhcNMjIxMDE0MjA1
+NDE3WjCBjDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzAp
+BgNVBAsTIlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcxODA2BgNV
+BAMTL1N0YXJ0Q29tIENsYXNzIDEgUHJpbWFyeSBJbnRlcm1lZGlhdGUgU2VydmVy
+IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtonGrO8JUngHrJJj
+0PREGBiEgFYfka7hh/oyULTTRwbw5gdfcA4Q9x3AzhA2NIVaD5Ksg8asWFI/ujjo
+/OenJOJApgh2wJJuniptTT9uYSAK21ne0n1jsz5G/vohURjXzTCm7QduO3CHtPn6
+6+6CPAVvkvek3AowHpNz/gfK11+AnSJYUq4G2ouHI2mw5CrY6oPSvfNx23BaKA+v
+WjhwRRI/ME3NO68X5Q/LoKldSKqxYVDLNM08XMML6BDAjJvwAwNi/rJsPnIO7hxD
+KslIDlc5xDEhyBDBLIf+VJVSH1I8MRKbf+fAoKVZ1eKPPvDVqOHXcDGpxLPPr21T
+Lwb0pwIDAQABo4IBTDCCAUgwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8E
+BAMCAQYwHQYDVR0OBBYEFOtCNNCYsKuf9BtrCPfMZC7vDixFMB8GA1UdIwQYMBaA
+FE4L7xqkQFulF2mHMMo0aEPQQa7yMGkGCCsGAQUFBwEBBF0wWzAnBggrBgEFBQcw
+AYYbaHR0cDovL29jc3Auc3RhcnRzc2wuY29tL2NhMDAGCCsGAQUFBzAChiRodHRw
+Oi8vYWlhLnN0YXJ0c3NsLmNvbS9jZXJ0cy9jYS5jcnQwMgYDVR0fBCswKTAnoCWg
+I4YhaHR0cDovL2NybC5zdGFydHNzbC5jb20vc2ZzY2EuY3JsMEMGA1UdIAQ8MDow
+OAYEVR0gADAwMC4GCCsGAQUFBwIBFiJodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9w
+b2xpY3kucGRmMA0GCSqGSIb3DQEBCwUAA4ICAQCBnsOw7dxamNbdJb/ydkh4Qb6E
+qgEU+G9hCCIGXwhWRZMYczNJMrpVvyLq5mNOmrFPC7bJrqYV+vEOYHNXrzthLyOG
+FFOVQe2cxbmQecFOvbkWVlYAIaTG42sHKVi+RFsG2jRNZcFhHnsFnLPMyE6148lZ
+wVdZGsxZvpeHReNUpW0jh7uq90sShFzHs4f7wJ5XmiHOL7fZbnFV6uE/OoFnBWif
+CRnd9+RE3uCospESPCRPdbG+Q4GQ+MBS1moXDTRB6DcNoHvqC6eU3r8/Fn/DeA9w
+9JHPXUfrAhZYKyOQUIqcfE5bvssaY+oODVxji6BMk8VSVHsJ4FSC1/7Pkt/UPoQp
+FVh38wIJnvEUeNVmVl3HHFYTd50irdKYPBC63qi2V/YYI6bJKmbrjfP9Vhyt9uNr
+y3Kh4W22ktDuCCvWC7n/gqerdq+VlTRfNt7D/mB0irnaKjEVNCXBXm9V/978J+Ez
+8aplGZccQ9jnc9kiPtUp5dj45E3V8vKqzp9srSSI5Xapdg+ZcPY+6HNuVB+MadRp
+ZW2One/Qnzg9B4GnVX7MOETImdoP4kXpostFuxoY/5LxCU1LJAIENV4txvT50lX2
+GBXCkxllRLWOgdyll11ift/4IO1aCOGDijGIfh498YisM1LGxytmGcxvbJERVri+
+gGpWAZ5J6dvtf0s+bA==
+-----END CERTIFICATE-----
+''',
+# https://class3.test.itk98.net/class1.ca.pem
+b'''
+-----BEGIN CERTIFICATE-----''' + b'''
+MIIGNDCCBBygAwIBAgIBGTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJ
+TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERp
+Z2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20g
+Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDcxMDI0MjA1NDE3WhcNMTcx
+MDI0MjA1NDE3WjCBjDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29t
+IEx0ZC4xKzApBgNVBAsTIlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNp
+Z25pbmcxODA2BgNVBAMTL1N0YXJ0Q29tIENsYXNzIDEgUHJpbWFyeSBJbnRl
+cm1lZGlhdGUgU2VydmVyIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAtonGrO8JUngHrJJj0PREGBiEgFYfka7hh/oyULTTRwbw5gdfcA4Q
+9x3AzhA2NIVaD5Ksg8asWFI/ujjo/OenJOJApgh2wJJuniptTT9uYSAK21ne
+0n1jsz5G/vohURjXzTCm7QduO3CHtPn66+6CPAVvkvek3AowHpNz/gfK11+A
+nSJYUq4G2ouHI2mw5CrY6oPSvfNx23BaKA+vWjhwRRI/ME3NO68X5Q/LoKld
+SKqxYVDLNM08XMML6BDAjJvwAwNi/rJsPnIO7hxDKslIDlc5xDEhyBDBLIf+
+VJVSH1I8MRKbf+fAoKVZ1eKPPvDVqOHXcDGpxLPPr21TLwb0pwIDAQABo4IB
+rTCCAakwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
+BBYEFOtCNNCYsKuf9BtrCPfMZC7vDixFMB8GA1UdIwQYMBaAFE4L7xqkQFul
+F2mHMMo0aEPQQa7yMGYGCCsGAQUFBwEBBFowWDAnBggrBgEFBQcwAYYbaHR0
+cDovL29jc3Auc3RhcnRzc2wuY29tL2NhMC0GCCsGAQUFBzAChiFodHRwOi8v
+d3d3LnN0YXJ0c3NsLmNvbS9zZnNjYS5jcnQwWwYDVR0fBFQwUjAnoCWgI4Yh
+aHR0cDovL3d3dy5zdGFydHNzbC5jb20vc2ZzY2EuY3JsMCegJaAjhiFodHRw
+Oi8vY3JsLnN0YXJ0c3NsLmNvbS9zZnNjYS5jcmwwgYAGA1UdIAR5MHcwdQYL
+KwYBBAGBtTcBAgEwZjAuBggrBgEFBQcCARYiaHR0cDovL3d3dy5zdGFydHNz
+bC5jb20vcG9saWN5LnBkZjA0BggrBgEFBQcCARYoaHR0cDovL3d3dy5zdGFy
+dHNzbC5jb20vaW50ZXJtZWRpYXRlLnBkZjANBgkqhkiG9w0BAQsFAAOCAgEA
+UiVivr7DGl0kxETnJMnlpLWn6AXQE+XSL2TdMkbS3wY40tqEo2O/MJ54cf1W
+QgZilw659qpXYmxMNX2VGo8rz2HxPcBMaU2mjRnVAyFXn2uLvTKUcBIu0Gs1
+qA75FBUOYxKudcreUaeWD2LlPgtdMX48mEU1VmjtDAHs1X7/z5j6c75c2VZ6
+9xx05z1MKm4+32xsntq3EdcmskUBc2VZNqs6iz1+cCBTQBdeP56f+1hFQ5Hi
+isQ8bDVdeENoFO99kHAAtjv4pkmj4BYqBUVWJy3VXxJcOk3QWyn5zwUps6EA
+JCAkY6u7rUiEhF4a3y7IV3llMx7V+lpkACGAKOlO2CVRohy+SDOiVGkzF+dz
+n+dx8Dzk+XX8ttFMh7G/IkbOBXLUOEuIDshnupkJZZdIFznMWAWN0iOj6qyb
+3+FwZAA5AZua5nrZrLeqK8ssn8L5sFQOfO9mwcgszBLr63VfH+y4WqSDyVj9
+mVv3yh6zTKYoXOMjH722m0oPwmgFsNLVrRSMtGt3Vvh0oSoDCjOi594tqTwa
+emktFyGcXud7db/MkwC2MU0DC1QZX3YQpjuP/keRY/U46/oOwaqI8JnhNd6x
+yn4H4ufzUAgl+Pu/aphb4RlClRuEL38a/Kq70wujW77vBXiEmjVOKnIkI2OE
+lZ/AyIQS/jZfAJX+NnYi6tU=
+-----END CERTIFICATE-----
+'''
+)
+
+class2 = (
+# https://www.startssl.com/certs/class2/sha2/pem/sub.class2.server.sha2.ca.pem
+b'''
+-----BEGIN CERTIFICATE-----''' + b'''
+MIIF2TCCA8GgAwIBAgIHHKs2Ry2cUTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQG
+EwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERp
+Z2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2Vy
+dGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDcxMDE0MjA1NzA5WhcNMjIxMDE0MjA1
+NzA5WjCBjDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzAp
+BgNVBAsTIlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcxODA2BgNV
+BAMTL1N0YXJ0Q29tIENsYXNzIDIgUHJpbWFyeSBJbnRlcm1lZGlhdGUgU2VydmVy
+IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4k85L6GMmoWtCA4I
+PlfyiAEhG5SpbOK426oZGEY6UqH1D/RujOqWjJaHeRNAUS8i8gyLhw9l33F0NENV
+sTUJm9m8H/rrQtCXQHK3Q5Y9upadXVACHJuRjZzArNe7LxfXyz6CnXPrB0KSss1k
+s3RVG7RLhiEs93iHMuAW5Nq9TJXqpAp+tgoNLorPVavD5d1Bik7mb2VsskDPF125
+w2oLJxGEd2H2wnztwI14FBiZgZl1Y7foU9O6YekO+qIw80aiuckfbIBaQKwn7UhH
+M7BUxkYa8zVhwQIpkFR+ZE3EMFICgtffziFuGJHXuKuMJxe18KMBL47SLoc6PbQp
+Z4rEAwIDAQABo4IBTDCCAUgwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8E
+BAMCAQYwHQYDVR0OBBYEFBHbI0X9VMxqcW+EigPXvvcBLyaGMB8GA1UdIwQYMBaA
+FE4L7xqkQFulF2mHMMo0aEPQQa7yMGkGCCsGAQUFBwEBBF0wWzAnBggrBgEFBQcw
+AYYbaHR0cDovL29jc3Auc3RhcnRzc2wuY29tL2NhMDAGCCsGAQUFBzAChiRodHRw
+Oi8vYWlhLnN0YXJ0c3NsLmNvbS9jZXJ0cy9jYS5jcnQwMgYDVR0fBCswKTAnoCWg
+I4YhaHR0cDovL2NybC5zdGFydHNzbC5jb20vc2ZzY2EuY3JsMEMGA1UdIAQ8MDow
+OAYEVR0gADAwMC4GCCsGAQUFBwIBFiJodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9w
+b2xpY3kucGRmMA0GCSqGSIb3DQEBCwUAA4ICAQBSyb3zvcv566LEMsqGcvzPv6cw
+tf2R99WB4SEErQBM/+mLJ9r/8iTN/B8Pf9LR5YGSI3gW7msDLp0ASE+ugmUuh2/u
+agdfS1Zu95ZGQebd/kW5Yiqainbprb3Wc7O8MSvQLNVsa7xqOiWHqailDdeF8Wxs
+BQ70wWjLuyqBWKU+mcSf9x+EjqB60U3buAGcDYE0yoL+I2JNP22kUsBMXvJpSLHy
+36xEZGmwRinHrfDywJ1oI4qoZ3EiF77OiXp2vlRsk1yL8Bpuru2OrsIFrhNX5rnn
+cMgzuJ79SjDjmNQTa+5Ouebs387qoJ52apeq6t80RUL12k3Wh3Zt/85phnqBX9uy
+T86w4GdgOUSwRRCFZZcSed/Ul9h4IQyEmM67T2sPGdqFaZFBbBccxrn2FK7yoYB6
+4umV7yKKzP842/whVuyA/W2ihZEpA+qrA70sYESCADXnFGx2O0CDVdVc38coo1nV
+iXg+D+AG/dVXiiQcp2I4HYWTS/mTf/NE+mOYnu0miZ32/vhDbCX/B/kSPJ4RsNOA
+7uyrOwykcgOSFDbpvuaKOpGLrQwGqLODgm+p9TY5giMMjur9XH7TS1wz02dIz07u
+y2NwYWdV67vcnAt6QxRISap5RbaPviyQZxz4nFaSlTAwHoPaW1yuVS11tmsROMlR
+RNvbaAxIU4U67YaZSw==
+-----END CERTIFICATE-----
+''',
+# https://class3.test.itk98.net/class2.ca.pem
+b'''
+-----BEGIN CERTIFICATE-----''' + b'''
+MIIGNDCCBBygAwIBAgIBGzANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJ
+TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERp
+Z2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20g
+Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDcxMDI0MjA1NzA5WhcNMTcx
+MDI0MjA1NzA5WjCBjDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29t
+IEx0ZC4xKzApBgNVBAsTIlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNp
+Z25pbmcxODA2BgNVBAMTL1N0YXJ0Q29tIENsYXNzIDIgUHJpbWFyeSBJbnRl
+cm1lZGlhdGUgU2VydmVyIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEA4k85L6GMmoWtCA4IPlfyiAEhG5SpbOK426oZGEY6UqH1D/RujOqW
+jJaHeRNAUS8i8gyLhw9l33F0NENVsTUJm9m8H/rrQtCXQHK3Q5Y9upadXVAC
+HJuRjZzArNe7LxfXyz6CnXPrB0KSss1ks3RVG7RLhiEs93iHMuAW5Nq9TJXq
+pAp+tgoNLorPVavD5d1Bik7mb2VsskDPF125w2oLJxGEd2H2wnztwI14FBiZ
+gZl1Y7foU9O6YekO+qIw80aiuckfbIBaQKwn7UhHM7BUxkYa8zVhwQIpkFR+
+ZE3EMFICgtffziFuGJHXuKuMJxe18KMBL47SLoc6PbQpZ4rEAwIDAQABo4IB
+rTCCAakwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
+BBYEFBHbI0X9VMxqcW+EigPXvvcBLyaGMB8GA1UdIwQYMBaAFE4L7xqkQFul
+F2mHMMo0aEPQQa7yMGYGCCsGAQUFBwEBBFowWDAnBggrBgEFBQcwAYYbaHR0
+cDovL29jc3Auc3RhcnRzc2wuY29tL2NhMC0GCCsGAQUFBzAChiFodHRwOi8v
+d3d3LnN0YXJ0c3NsLmNvbS9zZnNjYS5jcnQwWwYDVR0fBFQwUjAnoCWgI4Yh
+aHR0cDovL3d3dy5zdGFydHNzbC5jb20vc2ZzY2EuY3JsMCegJaAjhiFodHRw
+Oi8vY3JsLnN0YXJ0c3NsLmNvbS9zZnNjYS5jcmwwgYAGA1UdIAR5MHcwdQYL
+KwYBBAGBtTcBAgEwZjAuBggrBgEFBQcCARYiaHR0cDovL3d3dy5zdGFydHNz
+bC5jb20vcG9saWN5LnBkZjA0BggrBgEFBQcCARYoaHR0cDovL3d3dy5zdGFy
+dHNzbC5jb20vaW50ZXJtZWRpYXRlLnBkZjANBgkqhkiG9w0BAQsFAAOCAgEA
+bQjxXHkqUPtUY+u8NEFcuKMDITfjvGklLgrTuBW63grW+2AuDAZRo/066eNH
+s6QV4i5e4ujwPSR2dgggY7mOIIBmiDm2QRjF5CROq6zDlIdqlsFZICkuONDN
+FpFjaPtZRTmuK1n6gywQgCNSIrbzjPcwR/jL/wowbfwC9yGme1EeZRqvWy/H
+zFWacs7UMmWlRk6DTmpfPOPMJo5AxyTZCiCYQQeksV7xUAeY0kWa+y/FV+ee
+rOPUl6yy4jRHTk7tCySxrciZwYbd6YNLmeIQoUAdRC3CH3nTB2/JYxltcgyG
+HMiPU3TtafZgLs8fvncv+wIF1YAF/OGqg8qmzoJ3ghM4upGdTMIu8vADdmuL
+C/+dnbzknxX6QEGlWA8zojLUxVhGNfIFoizu/V/DyvSvYuxzzIkPECK5gDoM
+oBTTMI/wnxXwulNPtfgF7/5AtDhA4GNAfB2SddxiNQAF7XkUHtMZ9ff3W6Xk
+FldOG+NlLFqsDBG/KLckyFK36gq+FqNFCbmtmtXBGB5L1fDIeYzcMKG6hFQx
+hHS0oqpdHhp2nWBfLlOnTNqIZNJzOH37OJE6Olk45LNFJtSrqIAZyCCfM6bQ
+goQvZuIaxs9SIp+63ZMk9TxEaQj/KteaOyfaPXI9778U7JElMTz3Bls62msl
+V2I1C/A73ZyqJZWQZ8NU4ds=
+-----END CERTIFICATE-----
+'''
+)
+
+class3 = (
+# https://www.startssl.com/certs/class1/sha2/pem/sub.class3.server.sha2.ca.pem
+b'''
+-----BEGIN CERTIFICATE-----''' + b'''
+MIIF2TCCA8GgAwIBAgIHFahbcRCtzzANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQG
+EwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERp
+Z2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2Vy
+dGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDcxMDE0MjA1ODI0WhcNMjIxMDE0MjA1
+ODI0WjCBjDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29tIEx0ZC4xKzAp
+BgNVBAsTIlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNpZ25pbmcxODA2BgNV
+BAMTL1N0YXJ0Q29tIENsYXNzIDMgUHJpbWFyeSBJbnRlcm1lZGlhdGUgU2VydmVy
+IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxtTlmqySw6jNfvAT
+GV+1Z3tzCryzboJMuKv++wEh3XwM+fi1gAH9j8X6ORJYdCJcqWOA/D+E4Sh37S7x
+JR9JDCfpPo+6yS9G0D/pOuQjUZVCdBfGym0DOFrHfgaAtN+wy/rvVULObi1AYw7c
+F/a59olLMt5B41FNcbMCmJEBzmhc6iqttRqI0lGX72VDfcdEvOLw7rdEetvTl6hx
+/s/2B58j/NxVY5M3J/oeqY0sPOSc3RMrH1mWZ1xgS96FgeblRRxdNfRbDn1/qdrE
+Vxxc2jWHRyUUbpdevcgeTynGfBLcLsW9QUREZP2wGbeJL1TkbkMfxb/MKdQQzheL
+/9Gc2QIDAQABo4IBTDCCAUgwEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8E
+BAMCAQYwHQYDVR0OBBYEFIn4QqYcYurH8TIJK0E+e6JcrsVLMB8GA1UdIwQYMBaA
+FE4L7xqkQFulF2mHMMo0aEPQQa7yMGkGCCsGAQUFBwEBBF0wWzAnBggrBgEFBQcw
+AYYbaHR0cDovL29jc3Auc3RhcnRzc2wuY29tL2NhMDAGCCsGAQUFBzAChiRodHRw
+Oi8vYWlhLnN0YXJ0c3NsLmNvbS9jZXJ0cy9jYS5jcnQwMgYDVR0fBCswKTAnoCWg
+I4YhaHR0cDovL2NybC5zdGFydHNzbC5jb20vc2ZzY2EuY3JsMEMGA1UdIAQ8MDow
+OAYEVR0gADAwMC4GCCsGAQUFBwIBFiJodHRwOi8vd3d3LnN0YXJ0c3NsLmNvbS9w
+b2xpY3kucGRmMA0GCSqGSIb3DQEBCwUAA4ICAQAthLawLWmq9RJIhpczAyq3ep7T
+ccmBd50ifXNehjyJ5d90C/uflhRHe/tzGQKHGhgb/3jhW8k0HDfdqsGTZI6jkC+a
+Rld1X0cQMj/1NAXnOuMqhDXc5kANit9TdvtGlWZHVFvEk75JPYDD0D7ZXTQ3ccRn
+1CzQM9pX5uxp3eiVHh8zHVwbrVyxBi3zXTSD1sUP/Ze/aXPP/OYZl8y3Iy8cQpiq
+ie7OiiB1gOqp42Vb9lWnoH6jBLVpmtmkpcbH2wgClEmjgGTxmlILhD8BlrKF31vX
+j6KdlRwn+jA0Uz6DCD+1IWMaADMOzeG9P41upK5uESwvVUXImboBR/OXBMc8Jyg8
+WmPTG5rEwqkhGfsedq05kxg7MXmI7M2aaxXYwedkIGzhqrv6h3tLH/o8X9Ff7d0B
+SLK8wwGstLZ7vNv6K7q2bMv4g5mKaesPNg/hoTri4yJEbYVBL9xgvTLhvNGp46IY
+UEzn3vnFE6gnhne4jFQWqV4zjA9JveC8LtMqoAE8Z4HJbSNurfokLEm1MS3qIVHN
+po3bgKCaTKJhsOcWY3a38jb8GalRiqKJE5lKqvKvZ/gPWZVOl78qROiDfdWvBT00
+7p6y48YVkRW8Q1+M45w8cRaXfoRXbMJVCD9KvDrL2kDobaTvtIZxK0PUbKCXubPw
+0N8NcSQMxAONGPkXWw==
+-----END CERTIFICATE-----
+''',
+# https://class3.test.itk98.net/class3.ca.pem
+b'''
+-----BEGIN CERTIFICATE-----''' + b'''
+MIIGNDCCBBygAwIBAgIBHTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJ
+TDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERp
+Z2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20g
+Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDcxMDI0MjA1ODI0WhcNMTcx
+MDI0MjA1ODI0WjCBjDELMAkGA1UEBhMCSUwxFjAUBgNVBAoTDVN0YXJ0Q29t
+IEx0ZC4xKzApBgNVBAsTIlNlY3VyZSBEaWdpdGFsIENlcnRpZmljYXRlIFNp
+Z25pbmcxODA2BgNVBAMTL1N0YXJ0Q29tIENsYXNzIDMgUHJpbWFyeSBJbnRl
+cm1lZGlhdGUgU2VydmVyIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAxtTlmqySw6jNfvATGV+1Z3tzCryzboJMuKv++wEh3XwM+fi1gAH9
+j8X6ORJYdCJcqWOA/D+E4Sh37S7xJR9JDCfpPo+6yS9G0D/pOuQjUZVCdBfG
+ym0DOFrHfgaAtN+wy/rvVULObi1AYw7cF/a59olLMt5B41FNcbMCmJEBzmhc
+6iqttRqI0lGX72VDfcdEvOLw7rdEetvTl6hx/s/2B58j/NxVY5M3J/oeqY0s
+POSc3RMrH1mWZ1xgS96FgeblRRxdNfRbDn1/qdrEVxxc2jWHRyUUbpdevcge
+TynGfBLcLsW9QUREZP2wGbeJL1TkbkMfxb/MKdQQzheL/9Gc2QIDAQABo4IB
+rTCCAakwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
+BBYEFIn4QqYcYurH8TIJK0E+e6JcrsVLMB8GA1UdIwQYMBaAFE4L7xqkQFul
+F2mHMMo0aEPQQa7yMGYGCCsGAQUFBwEBBFowWDAnBggrBgEFBQcwAYYbaHR0
+cDovL29jc3Auc3RhcnRzc2wuY29tL2NhMC0GCCsGAQUFBzAChiFodHRwOi8v
+d3d3LnN0YXJ0c3NsLmNvbS9zZnNjYS5jcnQwWwYDVR0fBFQwUjAnoCWgI4Yh
+aHR0cDovL3d3dy5zdGFydHNzbC5jb20vc2ZzY2EuY3JsMCegJaAjhiFodHRw
+Oi8vY3JsLnN0YXJ0c3NsLmNvbS9zZnNjYS5jcmwwgYAGA1UdIAR5MHcwdQYL
+KwYBBAGBtTcBAgEwZjAuBggrBgEFBQcCARYiaHR0cDovL3d3dy5zdGFydHNz
+bC5jb20vcG9saWN5LnBkZjA0BggrBgEFBQcCARYoaHR0cDovL3d3dy5zdGFy
+dHNzbC5jb20vaW50ZXJtZWRpYXRlLnBkZjANBgkqhkiG9w0BAQsFAAOCAgEA
+SGTXnpQAUrMhzFcGLy/B/gNWS1zJ2j72py8ncV/rMxwBZdPwt6EUim63VwUA
+29wXrH6ANWF0UOBoaYJWyqkObaHY8cJuqbNhEl+WXGTZSqgjtgdqdICdIYvq
+Yya0rEj1Rr4tA9MoyG+1Xp4fPClHyMPAHcED5hWZ9wV0B2Rn8NOlbvmOj1dA
+QMfubRvxbKrWfAJ/J9KP+CntK/jh+v3EKSe1Jeyzn1pf0bz3pInkzfcxM53R
+6BWO24M3iVmAm3tY8uwwXFxv/3HVVgnorPXUFOxGujXPWv4m2LBtth7JH9CO
+vQwFCqYZut9vWb+0efgp3PkY2PgZtf3HEu7l51VedulrcVEiljno8cpDjagd
+b50YxNPvp6aAwxkV7wd3cgcGzS8YmbmQ8GLBCDTCcSmSIYKFIy9dTAu6C5s6
+0E6WeFHEtgNUoqzAXQ1zJLyQNRadhcM6f9lbjVCmv0/BvACOpGgAEEvjm4CY
+hKxZ+ob+KsEwXXQTT2HMa+bjBKopgj6VWTnf5j295YWP+3b0921AvZSzXDTi
+WIld8wrW3d89JxX69FuP3+CE85ryMxFwbuyITBYjnxDF9aFAlJOi5w7saXeB
+w1TvmYsilX3+fwnn5Nu4PZqw4MjxRcip15q6pz+SPjdhpYqFDQ3mgrvf4dMH
+ImruS2dA4t8bY/h8BARHrec=
+-----END CERTIFICATE-----
+'''
+)
+
+startcom_ca_certificates = (
+ ('class1', class1),
+ ('class2', class2),
+ ('class3', class3)
+)
+
+import argparse, os, logging, subprocess, sys
+_logger = logging.getLogger(__name__)
+
+def find_updated_cert(filename, ca_certificates):
+ '''
+ Returns None if the file contents do not contain the problematic
+ certificate, and the new file contents otherwise.
+ '''
+ contents = open(filename, 'rb').read()
+ if b'-----BEGIN CERTIFICATE-----' not in contents:
+ _logger.info('%s: not a certificate, skipping', filename)
+ return None
+ orig_contents = contents
+ for name, (old_cert, new_cert) in ca_certificates:
+ if not old_cert in contents:
+ continue
+ _logger.warning('%s: certificate needs update: %s', filename, name)
+ contents = contents.replace(old_cert, new_cert)
+
+ if orig_contents != contents:
+ return contents
+
+ _logger.info('%s: no changes needed', filename)
+
+def get_filenames(filenames, recursive):
+ '''
+ Discovers all files from the given set of filenames, optionally recursing
+ into directory items.
+ '''
+ while filenames:
+ item = filenames[0]
+ filenames = filenames[1:]
+ if os.path.isdir(item) and recursive:
+ try:
+ diritems = [os.path.join(item, filename)
+ for filename in os.listdir(item)]
+ except EnvironmentError as e:
+ _logger.warning('%s: %s', item, e)
+ continue
+ filenames = diritems + filenames
+ else:
+ yield item
+
+def main(args):
+ logLevel = logging.INFO if args.verbose else logging.WARNING
+ logging.basicConfig(format='%(message)s', level=logLevel)
+
+ if args.reverse:
+ ca_certificates = (
+ (name, (new_cert, old_cert))
+ for name, (old_cert, new_cert) in startcom_ca_certificates
+ )
+ else:
+ ca_certificates = startcom_ca_certificates
+
+ for filename in get_filenames(args.files, args.recursive):
+ try:
+ new_contents = find_updated_cert(filename, ca_certificates)
+ except EnvironmentError as e:
+ _logger.warning('%s: read error: %s', filename, e)
+ continue
+
+ # Do not write unmodified files, or when in read-only mode.
+ if not new_contents or not args.write:
+ continue
+
+ try:
+ open(filename, 'wb').write(new_contents)
+ _logger.warning('%s: wrote new certificate', filename)
+ except EnvironmentError as e:
+ _logger.warning('%s: write error: %s', filename, e)
+
+def print_certificate(pem):
+ sys.stdout.flush() # Flush buffered messages
+ p = subprocess.Popen(['openssl', 'x509', '-text'], stdin=subprocess.PIPE)
+ p.communicate(pem)
+
+def print_certificates():
+ for name, (old_cert, new_cert) in startcom_ca_certificates:
+ print('# Certificate %s:' % name)
+ print('')
+
+ print('## Problematic certificate:')
+ print_certificate(old_cert)
+ print('')
+
+ print('## Fixed certificate:')
+ print_certificate(new_cert)
+ print('')
+
+if __name__ == '__main__':
+ parser = argparse.ArgumentParser(description=__doc__.split('\n\n')[0])
+ parser.add_argument('-w', '--write', action='store_true',
+ help='Write new certificates besides printing changes.')
+ parser.add_argument('-r', '--recursive', action='store_true',
+ help='Recurse into directories.')
+ parser.add_argument('--reverse', action='store_true',
+ help='Replaces with the problematic certificate')
+ parser.add_argument('-v', '--verbose', action='store_true',
+ help='Be verbose, print skipped files')
+ parser.add_argument('files', metavar='file', nargs='*',
+ help='PEM-encoded certificate files')
+ parser.add_argument('--certificates', action='store_true',
+ help='Print certificates and exit')
+ args = parser.parse_args()
+
+ if args.certificates:
+ print_certificates()
+ else:
+ if not args.files:
+ parser.error('At least one PEM file is required')
+ main(args)