summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRemy <relst@relst.nl>2015-03-30 12:26:17 +0200
committerRemy <relst@relst.nl>2015-03-30 12:26:17 +0200
commitb470f3e3cb6fd341da0b4eed465d6165d98cd441 (patch)
tree5123b500c9d774cd2e2d6d961359343346d7a4f3
parentfaa7f20fcc89bb1a1b77f2aaa78b88cda794b1b5 (diff)
downloadssl-decoder-b470f3e3cb6fd341da0b4eed465d6165d98cd441.zip
ssl-decoder-b470f3e3cb6fd341da0b4eed465d6165d98cd441.tar.gz
ssl-decoder-b470f3e3cb6fd341da0b4eed465d6165d98cd441.tar.bz2
Add json endpoint
-rw-r--r--CHANGELOG.md5
-rw-r--r--README.md560
-rw-r--r--functions/connection.php1229
-rw-r--r--functions/crl.php79
-rw-r--r--functions/ocsp.php209
-rw-r--r--functions/parse_certificate.php1362
-rw-r--r--functions/textual.php6
-rw-r--r--functions/verify_certifitcate.php2
-rw-r--r--index.php2
-rw-r--r--json.php121
10 files changed, 2441 insertions, 1134 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bc8c22c..7e1fcd2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
# Changelog
+## 2.1
+
+- Add json API endpoint (see README)
+- Rewrote internals to use same endpoint
+
## 2.0
- Add TLS_FALLBACK_SCSV check
diff --git a/README.md b/README.md
index e7a34ce..68062e1 100644
--- a/README.md
+++ b/README.md
@@ -9,6 +9,7 @@ Simple PHP script which decodes an SSL connection and/or certificate and display
* Validates the certificate, chain, CRL and OCSP (of every cert in the chain)
* Has easy copy-pastable PEM versions of certs
* Ciphersuite enumeration as an option.
+* JSON API
* Fast.
### Features
@@ -28,6 +29,7 @@ Simple PHP script which decodes an SSL connection and/or certificate and display
- Full certificate chain validation.
- Issuer validation
- Date validation
+- JSON API
### Requirements
@@ -53,3 +55,561 @@ See [https://tls.so](https://tls.so).
### License
GNU Affero GPL v3: [https://www.gnu.org/licenses/agpl-3.0.html](https://www.gnu.org/licenses/agpl-3.0.html)
+
+
+### JSON API
+
+Endpoint: `/json.php`.
+
+
+
+Accepts:
+- CSR
+- Certificate
+- Host (+port, default 443)
+
+Returns JSON UTF-8 encoded certificate (and connection) data.
+
+Add `type=pretty` as parameter to get a pretty printed JSON (text/html). Otherwise just JSON (application/json).
+
+Examples:
+
+#### CSR
+
+Params:
+
+ - `csr` = PEM encoded certificate request
+
+Example Request:
+
+ json.php?csr=-----BEGIN+CERTIFICATE+REQUEST-----+%0D%0AMIIG8zCCBpgCAQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx+%0D%0AITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCBkgwggQ6BgcqhkjO+%0D%0AOAQBMIIELQKCAgEA5KY342mozvKAAICT4EXDMfnDw7HkribKi8vMy%2BHQXJ%2FhAoNs+%0D%0AByxZygZVc48Q0FA1wMcFC20RtdswMCuogBlUcNxmOCZe%2FmYIJxfp6EWi6ZG0vTA5+%0D%0An6a89iEnfgZ9s2xnhO%2FXiHFax8cjHujQPH3epAtVsBPoxIHsWtVZv%2Fp08L6xgSHl%0D%0AwCQB00fuAhWu60oF45vsQwD%2FvPtQnYFD2elDWivcz51YT8c9EyiXb6geHhGSJkAY%0D%0AVEXNPV7%2FMrAF9ufhc9ss9vrxRiAvBEW2KToL8%2FcYa%2B1L0%2FVEGgJ8jkhhSfiN2q13%0D%0A%2FwBMgG%2FKPr5v94qjeuM4fl6LPZqOjhoYTJJL3WWiAiUzMez30hz%2BE1TUe5f9VI%2Ba%0D%0A1BH%2FhFvlDhuIEyIfsmupzKf0RpzXbSkP%2F4v3PlOuiuOEza1mbZZSOXBGOdKYYC7K%0D%0ALtVb62MD0B%2FFvD8yKO5NQCwFbQC60tU6JyneJJFdqY0HUjHERC3FMDoXoEH%2Fv8b5%0D%0A93kDg8jvmwijh96HgxkssoiRxYp9a9IL%2BGQ1WYYtVTSCz8zgWZyo0W0%2B3bJ66oAg%0D%0Al%2BfZw98xSa0SG1bd8k4c6xVgp%2Bou3EPorbXdgZg31HKrbiFVuhuJFvP3fRHw2GGM%0D%0A9oyFdAGuf1mdQU4XwqoEmhcRnIkN4IF8aMz7VEawAbLgNmu8E9bWIrEjMCkCIQDv%0D%0AQXTIsw1pCZXmF6Yum2%2FgP6xqbCuL6Te4q7KQrPYTyQKCAgEAooejkz2e%2BfnMKnIM%0D%0AK1xMcR8%2FgnD0HDPnhZ5WSwEl%2BalDjAl1U15BdcjIFL%2FdpCRn6JwuM2uY3wtyVU6i%0D%0A2iW4dXsP7rkh2jZP008MQc1e2OrqscGgqpHwJyZa14bUDMbCp2rVYaR2IxLOKa98%0D%0AvbTq8YOBwT1rml1yUYoQHRoU5sFLomfqZILEfomx9w%2FSS9HH6iUYX6AGrGFi9Dqc%0D%0AyOrzkUYFh7c5JSLzvt8I2Q8hZMDz%2FUwuHkfQ%2FjUDZXtazUOhAjxUfvYDYqCMF%2F7R%0D%0AZPjkpo0yX8Rb13J50%2BUuPfOvrWl6nnK%2BNN8Y%2FRIBzaEvEsq6%2BH6mf0J3XFVGtIPy%0D%0AIulMe5iyTwyvdUHxxZzWjRY9apPw6Laoen4yK5D6IrqY2QCGvWZHgfa41raQEKtq%0D%0AXuubALxOtBxehEansfB2g7hY%2BNfFk0BskswhVqJw6EoLUJKPijXY9Kms%2FANXRpto%0D%0Au0Qzv76YZfJwg%2Faidowoewp%2B7cBAGZbRg1gcGU%2Fe9cFqmruwgy%2Bs2p6t3GamgSRn%0D%0AdwNCOe0R0UjdjZaieJLu6EkZK%2BdhcDXvlVd%2FRx2Vq62zKgYawvIsctdseUAs%2BGf6%0D%0Ajweb38m1uCyIyUkMrOH9GnxCkyiUAH05UJAXT3%2FhhS4sra6A74K%2BAF8wlpfxYY38%0D%0Aquo1Ai%2Bc9MBg%2FKWIVQrsinDI%2BKUDggIGAAKCAgEAkXIvCerLlpA%2FTP7joo0ruxkr%0D%0AGaHa0g0xLJp89r1eRbyzlZZPgsq1AqCfp0%2B2TYAe%2FZsn0Xs4R9n7S5lXIhKEO4YM%0D%0ACIOdWMCZL%2FZoeMzEv8ievxBoFLUQNMzTnRS9lOhaC3ew9JjQMszM5wRAtrdCVgnG%0D%0ACxWD4JC9okn%2F%2BnTSE5exLda%2FQ8BpXzKUuWSJaGYt1H1pRsUXsx0apZ2u%2FRyq6aI4%0D%0A2HwOKZN0%2FPV%2FoHQ8ayxu22dbfduY7YJ4zMkeovggR6tAoOKw4%2BxMMy82DKxpa%2Fkt%0D%0A5a%2B26Myf2dkzHH6ndgupjde%2FsZUifoJMib6i33DdT3TPwiJ1QvCK7cTlgO9CzeIZ%0D%0AssPBYC%2FfpV65Ih9wWJPaObDQPA5tt%2BtKTMOKwz9jmiaXFhmlGZtCahfll5xWXzVJ%0D%0AFbM6NxgYg0bErRcyck8Ngc5%2BO8fm3oGSotQ7eVh%2B%2B04J5g3vk9ufqbi02mFlpMZi%0D%0A%2FFykgQYbnCen%2BBxcO%2BboUMd4urqL0VpSu5NtBd8%2BqULWRrvBEf8s2IY3OaOQEvwJ%0D%0ANZhWJdNpg2lY%2BUmefxm9P9qQqfIhJ3LZavr3jfy81xVFqOciO1Xt7TfzVFqMGH1s%0D%0AaKyPCpApJQ%2BWPuM1WiAimGJFUgk5ZwHyqC8NFDA5wSr%2BfYR6NxZv3pFscb3PqxpQ%0D%0A6C%2BjnKYiyibu4indeE6gADALBglghkgBZQMEAwIDSAAwRQIgMvqOm1M55K0mNYL2%0D%0ArtHl2W%2F1zJufX7FlpAlR3UgoqdICIQDQoyoS8ND%2BjSUl1Pbn%2Buh6yzglP3vfvyxB%0D%0Ax1%2BT5MCUKw%3D%3D%0D%0A-----END+CERTIFICATE+REQUEST-----
+
+Response
+
+ {
+ "data": {
+ "chain": {
+ "1": {
+ "subject": {
+ "C": "AU",
+ "ST": "Some-State",
+ "O": "Internet Widgits Pty Ltd"
+ },
+ "key": "-----BEGIN PUBLIC KEY-----\nMIIGS[...]LKJu7iKd14Tg==\n-----END PUBLIC KEY-----\n",
+ "details": {
+ "bits": "4096",
+ "key": "-----BEGIN PUBLIC KEY-----\nMIIGS[...]LKJu7iKd14Tg==\n-----END PUBLIC KEY-----\n",
+ "dsa": {
+ "p": "...",
+ "q": "...",
+ "pub_key": "..."
+ },
+ "type": "1"
+ }
+ }
+ }
+ }
+ }
+
+
+#### Certificate
+
+Params:
+
+ - `csr` = PEM encoded certificate
+
+Example Request:
+
+ json.php?csr=-----BEGIN+CERTIFICATE-----%0D%0AMIIKmDCCBoCgAwIBAgIBAzANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMCTkwx%0D%0AFTATBgNVBAgMDFp1aWQgSG9sbGFuZDESMBAGA1UEBwwJUm90dGVyZGFtMRowGAYD%0D%0AVQQKDBFTcGFya2xpbmcgTmV0d29yazEVMBMGA1UECwwMU3BhcmtsaW5nIENBMRUw%0D%0AEwYDVQQDDAxTcGFya2xpbmcgQ0EwHhcNMTUwMzI5MTExMzU4WhcNMTcwMzI4MTEx%0D%0AMzU4WjBvMRMwEQYDVQQDDApnb29nbGUuY29tMRIwEAYDVQQIDAlSb3R0ZXJkYW0x%0D%0ACzAJBgNVBAYTAk5MMRowGAYDVQQKDBFTcGFya2xpbmcgTmV0d29yazEbMBkGA1UE%0D%0ACwwSU3BhcmtsaW5nIFdlYnNpdGVzMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC%0D%0ACgKCAgEAoi3dJz7UcdbIU%2BfM5S44tk8MM%2B%2BPguUDVnC2wviFgpg6Q%2BINGnAofUoe%0D%0Ay%2BCtiqNWZyey0QO9AglEX8Q0z3eTSTf29ntBgfMUwpMkkXuXDrdH78%2Fzh83L4VkO%0D%0Ar%2B87cRZi4clskcIE1DJrw%2FbN9oyRAjWdKZfpaMtLT9ab4yWNOCqy0gzxiG7NfAfv%0D%0AvqxF6Rwg9lNVJmRqwxP54qa2ayjmqVPhBgLqpRRfE2CPxxiCb8KdYhbFVaEraXKM%0D%0ARMFans%2BXSD6I5e0N3BTjAf2%2Bv6Dzjyt9sQFh%2FEpjqZrTe2JCwg3C44hy8RdohuN%2B%0D%0At0OsvAO46Xk7cP8Z%2FhqxSpcvNRhcjFQ6bCv74OXInVu5pSHydARSlM0FKfhAjaVl%0D%0Acu9Q%2FpkQ2rhFtvpKnJr%2B3tZiSlRpuK0MLDLMhgWopfMzXvBAzSxDC0hXODzjHA0M%0D%0AoTbW4vDmAv6bn%2BJXzxHsaxjkbpr1x2FRbwj8ZuwIzUIZP46iRVzZ97p%2B6D9LK40q%0D%0AhI50eiuFQfigqXoe5BrniQtkZi293H4dKJzvoLSAbjYB0PLD6I7zkNt8QtVDLhSz%0D%0A5u7fC890VYK9DZZP1B8RAYn91SRRFBBnJDSRgvutA%2FRSkXkLXviCw4oDIfijTrg4%0D%0AW35ASS5LjAOwbucKY3lsbd2lbLGcyxro9Z9aeLxZEX49X3u1dhUCAwEAAaOCAykw%0D%0AggMlMA8GA1UdEwEB%2FwQFMAMBAf8wHQYDVR0OBBYEFK8Cti%2BdB4641gUmn048XvPu%0D%0AhCs0MB8GA1UdIwQYMBaAFKyJWGQeqG3MO7k4TliuqefL7do3MAsGA1UdDwQEAwIF%0D%0AoDATBgNVHSUEDDAKBggrBgEFBQcDATCCASQGA1UdHwSCARswggEXMEmgR6BFhkNo%0D%0AdHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9SU0FEb21haW5WYWxpZGF0aW9u%0D%0AU2VjdXJlU2VydmVyQ0EuY3JsMEGgP6A9hjtodHRwOi8vY3JsLmNvbW9kb2NhLmNv%0D%0AbS9DT01PRE9SU0FDZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDA0oDKgMIYuaHR0%0D%0AcDovL2NybC5wa2lvdmVyaGVpZC5ubC9Sb290TGF0ZXN0Q1JMLUcyLmNybDAgoB6g%0D%0AHIYaaHR0cDovL3NyLnN5bWNiLmNvbS9zci5jcmwwL6AtoCuGKWh0dHA6Ly9jcmwu%0D%0AdGNzLnRlcmVuYS5vcmcvVEVSRU5BU1NMQ0EuY3JsMFEGA1UdEQRKMEiCCyouZ29v%0D%0AZ2xlLm5sggpnb29nbGUuY29tggwqLmdvb2dsZS5jb22CBSouY29tggpyYXltaWku%0D%0Ab3JnggwqLnJheW1paS5vcmcwggEzBggrBgEFBQcBAQSCASUwggEhME8GCCsGAQUF%0D%0ABzAChkNodHRwOi8vY3J0LmNvbW9kb2NhLmNvbS9DT01PRE9SU0FEb21haW5WYWxp%0D%0AZGF0aW9uU2VjdXJlU2VydmVyQ0EuY3J0MCYGCCsGAQUFBzAChhpodHRwOi8vc3Iu%0D%0Ac3ltY2IuY29tL3NyLmNydDAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuY29tb2Rv%0D%0AY2EuY29tMDcGCCsGAQUFBzABhitodHRwOi8vb2NzcC5kaWdpZGVudGl0eS5ldS9M%0D%0ANC9zZXJ2aWNlcy9vY3NwMB8GCCsGAQUFBzABhhNodHRwOi8vc3Iuc3ltY2QuY29t%0D%0AMCYGCCsGAQUFBzABhhpodHRwOi8vb2NzcC50Y3MudGVyZW5hLm9yZzANBgkqhkiG%0D%0A9w0BAQUFAAOCBAEAWM5iu%2F7PUCJyhN3nR77FxCWanLeAIWU8NJEpspjZgjH5j0Oc%0D%0A8mqYmJEzfrIg4O%2F9ZoqrUV1OiDW7fyf7DHW9yTwmcc%2Fwute05TRN3dtUXmzNMk6B%0D%0ABfaBbwuXjL8ZEZcZnHKSvWxMmqG2Rx3csA68I53qluedP2b61dQiTwiBa1SH4v3G%0D%0A78ZeJi03RSoB6Fbn6l%2BcIfPNI877d%2BpzOvBs05Vj57bdb%2B7Ji0lzDWQNV7uuc3%2FR%0D%0AWVEfZv0ErBgVxlI3EautBQaGZCf1ltwyo2n8wTkVou6wFIX5K4LkWOYuSiu%2FcgB3%0D%0A%2BOl21TGZf%2BoqhMCkmYp313MSbu8HUO7COpJI0B4IZ4Zm%2BYelKGjhDX8bx5l4TrGh%0D%0AfbsuoHpesRx3%2FzEnoP4VGAkuN7H5PALhF3G%2FRI8jKwBdLA3ANhochqsICmvu9Li2%0D%0ASJAxT87%2Fh4azUYGvd9ZnEWl5rMSqZkFtZhw0y%2FPVKgw0rXuaVfvqqSuETeq6gGp1%0D%0ALYtJUq4LO4Yvg7QXxa1qCeZmTbea%2BQmE%2BWsi0jPYQ3LkLkOpDh9nsuY3Ru7f%2BgIB%0D%0AdELs2TTpOKcg7eKLEpv8JGLXv0NYwc1aqKyL6jycjeGCC9riw8Xla3ZLgAx4IJyM%0D%0AJV7qRUxg4jMK%2BpQd5q1Z3RX5PIwPdzFkHdBnPH6k7GCOqEzQnmR8Hql9xUwi5svM%0D%0AiitX4Y7FbXW1zxzaBX6SLCfE60lUhSh7ik%2Bb9TK77Gg%2FuLDmdanXpFguSezGCHZ2%0D%0AjL4mYLeXWV88WVXEH4tmXsCQrQsmnlcTAJpvXW7NvV8lCjqh3RbXXG7RHd2IEWfr%0D%0AZAAaT%2BnwNIW%2Fx8mXJxUx9RpCKVS%2BCm8Q%2FjDHT9X7DxdHlzzzvN%2Brv8yy6P%2Fp8HGP%0D%0AY84H84qVP9uQgoAxArKRIVIO7ZjaT38V5tlidTxjyf38y0E%2FHV%2BLM2vjl3wsefQw%0D%0AU8dzNGCNvEWycVrBrZArjITkHFMq%2F3VUODlX4M3GTZ4XuZR%2BEGB0kF3uyApE%2FfLX%0D%0AP4qzfsTw%2F0p0Xn7K%2Ff3HsYyyXbh17sR761gbQCXHJN1YE0F5U4F7DESgbhWZrLJ6%0D%0AtCG5Np%2FmrQ7rKIJxKqSdSKicKYgi0lSk0bq9eF0QLDvECiCiEDT33D8ju%2BKjPXie%0D%0Ad6bddv3wUguPUOg7hYr1DLaRwZ9FtfM2UqYtEQxwuebDragUY2gO0tT2wtqNFhwl%0D%0AXnPFJhWi3Atz%2FcjvdlktvhhaqHJLUkmaXVsgys470rUUq%2BJETCUVM8dKYfC3Nir1%0D%0APcl%2Bic8lyHLRserIynKLsnYlCgMb6DdbyMXWUUe2OGuUvz9OI09VjY8vAnKfM0E0%0D%0AQ3aqS6U2xoswso%2Bov1HkVOOlcNFpJAqQ7pn4iA%3D%3D%0D%0A-----END+CERTIFICATE-----%0D%0A
+
+Example Response:
+
+ {
+ "data": {
+ "chain": {
+ "1": {
+ "cert_data": {
+ "name": "/CN=google.com/ST=Rotterdam/C=NL/O=Sparkling Network/OU=Sparkling Websites",
+ "subject": {
+ "CN": "google.com",
+ "ST": "Rotterdam",
+ "C": "NL",
+ "O": "Sparkling Network",
+ "OU": "Sparkling Websites"
+ },
+ "hash": "ceef4183",
+ "issuer": {
+ "C": "NL",
+ "ST": "Zuid Holland",
+ "L": "Rotterdam",
+ "O": "Sparkling Network",
+ "OU": "Sparkling CA",
+ "CN": "Sparkling CA"
+ },
+ "version": "2",
+ "serialNumber": "3",
+ "validFrom": "150329111358Z",
+ "validTo": "170328111358Z",
+ "validFrom_time_t": "1427627638",
+ "validTo_time_t": "1490699638",
+ "extensions": {
+ "basicConstraints": "CA:TRUE",
+ "subjectKeyIdentifier": "AF:02:B6:2F:9D:07:8E:B8:D6:05:26:9F:4E:3C:5E:F3:EE:84:2B:34",
+ "authorityKeyIdentifier": "keyid:AC:89:58:64:1E:A8:6D:CC:3B:B9:38:4E:58:AE:A9:E7:CB:ED:DA:37\n",
+ "keyUsage": "Digital Signature, Key Encipherment",
+ "extendedKeyUsage": "TLS Web Server Authentication",
+ "crlDistributionPoints": "\nFull Name:\n URI:http://crl.comodoca.com/COMODORSADomainValidationSecureServerCA.crl\n\nFull Name:\n URI:http://crl.comodoca.com/COMODORSACertificationAuthority.crl\n\nFull Name:\n URI:http://crl.pkioverheid.nl/RootLatestCRL-G2.crl\n\nFull Name:\n URI:http://sr.symcb.com/sr.crl\n\nFull Name:\n URI:http://crl.tcs.terena.org/TERENASSLCA.crl\n",
+ "subjectAltName": "DNS:*.google.nl, DNS:google.com, DNS:*.google.com, DNS:*.com, DNS:raymii.org, DNS:*.raymii.org",
+ "authorityInfoAccess": "CA Issuers - URI:http://crt.comodoca.com/COMODORSADomainValidationSecureServerCA.crt\nCA Issuers - URI:http://sr.symcb.com/sr.crt\nOCSP - URI:http://ocsp.comodoca.com\nOCSP - URI:http://ocsp.digidentity.eu/L4/services/ocsp\nOCSP - URI:http://sr.symcd.com\nOCSP - URI:http://ocsp.tcs.terena.org\n"
+ },
+ "purposes": {
+ "sslclient": {
+ "ca": "",
+ "general": ""
+ },
+ "sslserver": {
+ "ca": "",
+ "general": "1"
+ },
+ "nssslserver": {
+ "ca": "",
+ "general": "1"
+ },
+ "smimesign": {
+ "ca": "",
+ "general": ""
+ },
+ "smimeencrypt": {
+ "ca": "",
+ "general": ""
+ },
+ "crlsign": {
+ "ca": "",
+ "general": ""
+ },
+ "any": {
+ "ca": "1",
+ "general": "1"
+ },
+ "ocsphelper": {
+ "ca": "",
+ "general": "1"
+ },
+ "timestampsign": {
+ "ca": "",
+ "general": ""
+ }
+ }
+ },
+ "validation_type": "organisation",
+ "crl": {
+ "1": {
+ "crl_uri": "http://crl.comodoca.com/COMODORSADomainValidationSecureServerCA.crl",
+ "status": "ok",
+ "crl_last_update": "Mar 30 00:56:21 2015 GMT\n",
+ "crl_next_update": "Apr 3 00:56:21 2015 GMT\n"
+ },
+ "2": {
+ "crl_uri": "http://crl.comodoca.com/COMODORSACertificationAuthority.crl",
+ "status": "ok",
+ "crl_last_update": "Mar 29 19:04:22 2015 GMT\n",
+ "crl_next_update": "Apr 2 19:04:22 2015 GMT\n"
+ },
+ "3": {
+ "crl_uri": "http://crl.pkioverheid.nl/RootLatestCRL-G2.crl",
+ "status": "ok",
+ "crl_last_update": "Jan 8 10:19:45 2015 GMT\n",
+ "crl_next_update": "Jan 8 10:24:45 2016 GMT\n"
+ },
+ "4": {
+ "crl_uri": "http://sr.symcb.com/sr.crl",
+ "status": "ok",
+ "crl_last_update": "Mar 30 09:01:05 2015 GMT\n",
+ "crl_next_update": "Apr 6 09:01:05 2015 GMT\n"
+ },
+ "5": {
+ "crl_uri": "http://crl.tcs.terena.org/TERENASSLCA.crl",
+ "status": "ok",
+ "crl_last_update": "Mar 29 16:28:00 2015 GMT\n",
+ "crl_next_update": "Apr 2 16:28:00 2015 GMT\n"
+ }
+ },
+ "ocsp": "No OCSP URI found in certificate",
+ "hostname_in_san_or_cn": "n/a; ca signing certificate",
+ "serial": "3",
+ "key": {
+ "type": "rsa",
+ "bits": "4096",
+ "signature_algorithm": "sha1WithRSAEncryption",
+ "certificate_pem": "-----BEGIN CERTIFICATE-----\nMIIK[...]Q7pn4iA==\n-----END CERTIFICATE-----\n",
+ "public_key_pem": "-----BEGIN PUBLIC KEY-----\nMIIC[...]UCAwEAAQ==\n-----END PUBLIC KEY-----\n",
+ "spki_hash": "MQEUI8vhXsSgP7y58AWpE3xfqepYOHILKdHRewQSWkE="
+ }
+ }
+ }
+ }
+ }
+
+
+#### Hostname + Port
+
+Params:
+
+ - `host` = Hostname or IP address
+ - `port` = port to test (443, 993, 465, 8443 etc).
+ - ciphersuites = 1 to enumerate ciphersuites supported by the tested server. Takes longer. If not specified or not 1, ciphersuites will not be tested, used ciphersuite will be reported.
+
+
+Port is optional and defaults to 443. Ciphersuites is optional and defaults to 0.
+
+Example request:
+
+ json.php?host=mijn.ing.nl&ciphersuites=1
+
+Example response:
+
+ {
+ "data": {
+ "connection": {
+ "chain": {
+ "0": {
+ "name": "mijn.ing.nl",
+ "issuer": "Symantec Class 3 EV SSL CA - G3"
+ },
+ "1": {
+ "name": "Symantec Class 3 EV SSL CA - G3",
+ "issuer": "VeriSign Class 3 Public Primary Certification Authority - G5"
+ },
+ "validation": {
+ "status": "success"
+ }
+ },
+ "ip": "145.221.194.139",
+ "hostname": "145.221.194.139",
+ "port": "443",
+ "protocols": {
+ "tlsv1.2": "1",
+ "tlsv1.1": "",
+ "tlsv1.0": "1",
+ "sslv3": ""
+ },
+ "supported_ciphersuites": [
+ "AES256-SHA256",
+ "AES256-SHA",
+ "AES128-SHA256",
+ "AES128-SHA",
+ "DES-CBC3-SHA"
+ ],
+ "tls_fallback_scsv": "unsupported",
+ "strict_transport_security": "max-age=31622400",
+ "public_key_pins": "not set",
+ "ocsp_stapling": "not set",
+ "openssl_version": "OpenSSL 1.0.2a 19 Mar 2015\n",
+ "datetime_rfc2822": "Mon, 30 Mar 2015 12:18:11 +0200\n"
+ },
+ "chain": {
+ "1": {
+ "cert_data": {
+ "name": "/jurisdictionC=NL/businessCategory=Private Organization/serialNumber=33031431/C=NL/postalCode=1102 MG/ST=Noord-Holland/L=Amsterdam Zuidoost/street=Bijlmerplein 888/O=ING BANK N.V./OU=Retail/CN=mijn.ing.nl",
+ "subject": {
+ "jurisdictionC": "NL",
+ "businessCategory": "Private Organization",
+ "serialNumber": "33031431",
+ "C": "NL",
+ "postalCode": "1102 MG",
+ "ST": "Noord-Holland",
+ "L": "Amsterdam Zuidoost",
+ "street": "Bijlmerplein 888",
+ "O": "ING BANK N.V.",
+ "OU": "Retail",
+ "CN": "mijn.ing.nl"
+ },
+ "hash": "0ede29ea",
+ "issuer": {
+ "C": "US",
+ "O": "Symantec Corporation",
+ "OU": "Symantec Trust Network",
+ "CN": "Symantec Class 3 EV SSL CA - G3"
+ },
+ "version": "2",
+ "serialNumber": "58839941462596964668433973121388685875",
+ "validFrom": "140918000000Z",
+ "validTo": "161029235959Z",
+ "validFrom_time_t": "1410998400",
+ "validTo_time_t": "1477785599",
+ "extensions": {
+ "subjectAltName": "DNS:mijn.ing.nl",
+ "basicConstraints": "CA:FALSE",
+ "keyUsage": "Digital Signature, Key Encipherment",
+ "extendedKeyUsage": "TLS Web Server Authentication, TLS Web Client Authentication",
+ "certificatePolicies": "Policy: 2.16.840.1.113733.1.7.23.6\n CPS: https://d.symcb.com/cps\n User Notice:\n Explicit Text: https://d.symcb.com/rpa\n",
+ "authorityKeyIdentifier": "keyid:01:59:AB:E7:DD:3A:0B:59:A6:64:63:D6:CF:20:07:57:D5:91:E7:6A\n",
+ "crlDistributionPoints": "\nFull Name:\n URI:http://sr.symcb.com/sr.crl\n",
+ "authorityInfoAccess": "OCSP - URI:http://sr.symcd.com\nCA Issuers - URI:http://sr.symcb.com/sr.crt\n"
+ },
+ "purposes": {
+ "sslclient": {
+ "ca": "",
+ "general": "1"
+ },
+ "sslserver": {
+ "ca": "",
+ "general": "1"
+ },
+ "nssslserver": {
+ "ca": "",
+ "general": "1"
+ },
+ "smimesign": {
+ "ca": "",
+ "general": ""
+ },
+ "smimeencrypt": {
+ "ca": "",
+ "general": ""
+ },
+ "crlsign": {
+ "ca": "",
+ "general": ""
+ },
+ "any": {
+ "ca": "1",
+ "general": "1"
+ },
+ "ocsphelper": {
+ "ca": "",
+ "general": "1"
+ },
+ "timestampsign": {
+ "ca": "",
+ "general": ""
+ }
+ }
+ },
+ "validation_type": "extended",
+ "crl": {
+ "1": {
+ "crl_uri": "http://sr.symcb.com/sr.crl",
+ "status": "ok",
+ "crl_last_update": "Mar 30 09:01:05 2015 GMT\n",
+ "crl_next_update": "Apr 6 09:01:05 2015 GMT\n"
+ }
+ },
+ "ocsp": {
+ "1": {
+ "status": "good",
+ "this_update": "Mar 27 09:39:42 2015 GMT",
+ "next_update": "Apr 3 09:39:42 2015 GMT",
+ "ocsp_uri": "http://sr.symcd.com"
+ }
+ },
+ "hostname_in_san_or_cn": "false",
+ "serial": "319",
+ "key": {
+ "type": "rsa",
+ "bits": "2048",
+ "signature_algorithm": "sha256WithRSAEncryption",
+ "certificate_pem": "-----BEGIN CERTIFICATE-----\nMII[...]5rbdag==\n-----END CERTIFICATE-----\n",
+ "public_key_pem": "-----BEGIN PUBLIC KEY-----\nMII[...]DAQAB\n-----END PUBLIC KEY-----\n",
+ "spki_hash": "Y4ViGKugRm0tW3lflAY9ZGTj6xga6CtiZpMwzbCZARs="
+ }
+ },
+ "2": {
+ "cert_data": {
+ "name": "/C=US/O=Symantec Corporation/OU=Symantec Trust Network/CN=Symantec Class 3 EV SSL CA - G3",
+ "subject": {
+ "C": "US",
+ "O": "Symantec Corporation",
+ "OU": "Symantec Trust Network",
+ "CN": "Symantec Class 3 EV SSL CA - G3"
+ },
+ "hash": "a0f7ac3e",
+ "issuer": {
+ "C": "US",
+ "O": "VeriSign, Inc.",
+ "OU": [
+ "VeriSign Trust Network",
+ "(c) 2006 VeriSign, Inc. - For authorized use only"
+ ],
+ "CN": "VeriSign Class 3 Public Primary Certification Authority - G5"
+ },
+ "version": "2",
+ "serialNumber": "168652503989349361584430187274382793396",
+ "validFrom": "131031000000Z",
+ "validTo": "231030235959Z",
+ "validFrom_time_t": "1383177600",
+ "validTo_time_t": "1698710399",
+ "extensions": {
+ "authorityInfoAccess": "OCSP - URI:http://s2.symcb.com\n",
+ "basicConstraints": "CA:TRUE, pathlen:0",
+ "certificatePolicies": "Policy: X509v3 Any Policy\n CPS: http://www.symauth.com/cps\n User Notice:\n Explicit Text: http://www.symauth.com/rpa\n",
+ "crlDistributionPoints": "\nFull Name:\n URI:http://s1.symcb.com/pca3-g5.crl\n",
+ "keyUsage": "Certificate Sign, CRL Sign",
+ "subjectAltName": "DirName: CN = SymantecPKI-1-533",
+ "subjectKeyIdentifier": "01:59:AB:E7:DD:3A:0B:59:A6:64:63:D6:CF:20:07:57:D5:91:E7:6A",
+ "authorityKeyIdentifier": "keyid:7F:D3:65:A7:C2:DD:EC:BB:F0:30:09:F3:43:39:FA:02:AF:33:31:33\n"
+ },
+ "purposes": {
+ "sslclient": {
+ "ca": "1",
+ "general": ""
+ },
+ "sslserver": {
+ "ca": "1",
+ "general": ""
+ },
+ "nssslserver": {
+ "ca": "1",
+ "general": ""
+ },
+ "smimesign": {
+ "ca": "1",
+ "general": ""
+ },
+ "smimeencrypt": {
+ "ca": "1",
+ "general": ""
+ },
+ "crlsign": {
+ "ca": "1",
+ "general": "1"
+ },
+ "any": {
+ "ca": "1",
+ "general": "1"
+ },
+ "ocsphelper": {
+ "ca": "1",
+ "general": "1"
+ },
+ "timestampsign": {
+ "ca": "1",
+ "general": ""
+ }
+ }
+ },
+ "validation_type": "organisation",
+ "crl": {
+ "1": {
+ "crl_uri": "http://s1.symcb.com/pca3-g5.crl",
+ "status": "ok",
+ "crl_last_update": "Mar 18 00:00:00 2015 GMT\n",
+ "crl_next_update": "Jun 30 23:59:59 2015 GMT\n"
+ }
+ },
+ "ocsp": {
+ "1": {
+ "status": "good",
+ "this_update": "Mar 30 08:09:41 2015 GMT",
+ "next_update": "Apr 6 08:09:41 2015 GMT",
+ "ocsp_uri": "http://s2.symcb.com"
+ }
+ },
+ "hostname_in_san_or_cn": "n/a; ca signing certificate",
+ "serial": "105",
+ "key": {
+ "type": "rsa",
+ "bits": "2048",
+ "signature_algorithm": "sha256WithRSAEncryption",
+ "certificate_pem": "-----BEGIN CERTIFICATE-----\nMIIF[...]tO7w+Q==\n-----END CERTIFICATE-----\n",
+ "public_key_pem": "-----BEGIN PUBLIC KEY-----\nMII[...]ww0\nDwIDAQAB\n-----END PUBLIC KEY-----\n",
+ "spki_hash": "gMxWOrX4PMQesK9qFNbYBxjBfjUvlkn/vN1n+L9lE5E="
+ }
+ },
+ "3": {
+ "cert_data": {
+ "name": "/C=US/O=VeriSign, Inc./OU=VeriSign Trust Network/OU=(c) 2006 VeriSign, Inc. - For authorized use only/CN=VeriSign Class 3 Public Primary Certification Authority - G5",
+ "subject": {
+ "C": "US",
+ "O": "VeriSign, Inc.",
+ "OU": [
+ "VeriSign Trust Network",
+ "(c) 2006 VeriSign, Inc. - For authorized use only"
+ ],
+ "CN": "VeriSign Class 3 Public Primary Certification Authority - G5"
+ },
+ "hash": "b204d74a",
+ "issuer": {
+ "C": "US",
+ "O": "VeriSign, Inc.",
+ "OU": "Class 3 Public Primary Certification Authority"
+ },
+ "version": "2",
+ "serialNumber": "49248466687453522052688216172288342269",
+ "validFrom": "061108000000Z",
+ "validTo": "211107235959Z",
+ "validFrom_time_t": "1162944000",
+ "validTo_time_t": "1636329599",
+ "extensions": {
+ "basicConstraints": "CA:TRUE",
+ "crlDistributionPoints": "\nFull Name:\n URI:http://crl.verisign.com/pca3.crl\n",
+ "keyUsage": "Certificate Sign, CRL Sign",
+ "certificatePolicies": "Policy: X509v3 Any Policy\n CPS: https://www.verisign.com/cps\n",
+ "subjectKeyIdentifier": "7F:D3:65:A7:C2:DD:EC:BB:F0:30:09:F3:43:39:FA:02:AF:33:31:33",
+ "1.3.6.1.5.5.7.1.12": "0_¡] [0Y0W0U\u0016\timage/gif0!0\u001f0\u0007\u0006\u0005+\u000e\u0003\u0002\u001a\u0004\u0014åÓ\u001a†¬ŽkÃπjÔH\u0018,{\u0019.0%\u0016#http://logo.verisign.com/vslogo.gif",
+ "authorityInfoAccess": "OCSP - URI:http://ocsp.verisign.com\n",
+ "extendedKeyUsage": "TLS Web Server Authentication, TLS Web Client Authentication, Code Signing, Netscape Server Gated Crypto, 2.16.840.1.113733.1.8.1"
+ },
+ "purposes": {
+ "sslclient": {
+ "ca": "1",
+ "general": ""
+ },
+ "sslserver": {
+ "ca": "1",
+ "general": ""
+ },
+ "nssslserver": {
+ "ca": "1",
+ "general": ""
+ },
+ "smimesign": {
+ "ca": "",
+ "general": ""
+ },
+ "smimeencrypt": {
+ "ca": "",
+ "general": ""
+ },
+ "crlsign": {
+ "ca": "1",
+ "general": "1"
+ },
+ "any": {
+ "ca": "1",
+ "general": "1"
+ },
+ "ocsphelper": {
+ "ca": "1",
+ "general": "1"
+ },
+ "timestampsign": {
+ "ca": "1",
+ "general": ""
+ }
+ }
+ },
+ "validation_type": "organisation",
+ "crl": {
+ "1": {
+ "crl_uri": "http://crl.verisign.com/pca3.crl",
+ "status": "ok",
+ "crl_last_update": "Mar 18 00:00:00 2015 GMT\n",
+ "crl_next_update": "Jun 30 23:59:59 2015 GMT\n"
+ }
+ },
+ "ocsp": "No OCSP URI found in certificate",
+ "hostname_in_san_or_cn": "n/a; ca signing certificate",
+ "serial": "234",
+ "key": {
+ "type": "rsa",
+ "bits": "2048",
+ "signature_algorithm": "sha1WithRSAEncryption",
+ "certificate_pem": "-----BEGIN CERTIFICATE-----\nMIIE0DCCB[...]JjhJ+xr3/\n-----END CERTIFICATE-----\n",
+ "public_key_pem": "-----BEGIN PUBLIC KEY-----\nMII[...]QAB\n-----END PUBLIC KEY-----\n",
+ "spki_hash": "JbQbUG5JMJUoI6brnx0x3vZF6jilxsapbXGVfjhN8Fg="
+ }
+ }
+ }
+ }
+ } \ No newline at end of file
diff --git a/functions/connection.php b/functions/connection.php
index c9705ac..b1b318e 100644
--- a/functions/connection.php
+++ b/functions/connection.php
@@ -15,37 +15,36 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
function fixed_gethostbyname($host) {
- $ip = gethostbyname($host);
- if ($ip != $host) {
- return $ip;
- } else {
- return false;
- }
+ $ip = gethostbyname($host);
+ if ($ip != $host) {
+ return $ip;
+ } else {
+ return false;
+ }
}
function get(&$var, $default=null) {
- return isset($var) ? $var : $default;
+ return isset($var) ? $var : $default;
}
function server_http_headers($host, $port){
- stream_context_set_default(
- array("ssl" =>
- array("verify_peer" => false,
- "capture_session_meta" => true,
- "verify_peer_name" => false,
- "allow_self_signed" => true,
- "sni_enabled" => true),
- 'http' => array(
- 'method' => 'GET'
- )
- )
- );
- $headers = get_headers("https://$host:$port", 1);
-
- if (!empty($headers)) {
- $headers = array_change_key_case($headers, CASE_LOWER);
- return $headers;
- }
+ stream_context_set_default(
+ array("ssl" =>
+ array("verify_peer" => false,
+ "capture_session_meta" => true,
+ "verify_peer_name" => false,
+ "allow_self_signed" => true,
+ "sni_enabled" => true),
+ 'http' => array(
+ 'method' => 'GET'
+ )
+ )
+ );
+ $headers = get_headers("https://$host:$port", 1);
+ if (!empty($headers)) {
+ $headers = array_change_key_case($headers, CASE_LOWER);
+ return $headers;
+ }
}
function ssl_conn_ciphersuites($host, $port, $ciphersuites){
@@ -142,476 +141,790 @@ function ssl_conn_ciphersuites($host, $port, $ciphersuites){
function ssl_conn_metadata($host, $port, $chain=null) {
global $random_blurp;
global $current_folder;
-$stream = stream_context_create (array("ssl" =>
- array("verify_peer" => false,
- "capture_session_meta" => true,
- "verify_peer_name" => false,
- "allow_self_signed" => true,
- "sni_enabled" => true)));
-$read_stream = stream_socket_client("ssl://$host:$port", $errno, $errstr, 2, STREAM_CLIENT_CONNECT, $stream);
-if ( $read_stream === false ) {
- return false;
-} else {
- $context = stream_context_get_params($read_stream);
- $context_meta = stream_context_get_options($read_stream)['ssl']['session_meta'];
- $cert_data = openssl_x509_parse($context["options"]["ssl"]["peer_certificate"])[0];
+ $stream = stream_context_create (array("ssl" =>
+ array("verify_peer" => false,
+ "capture_session_meta" => true,
+ "verify_peer_name" => false,
+ "allow_self_signed" => true,
+ "sni_enabled" => true)));
+ $read_stream = stream_socket_client("ssl://$host:$port", $errno, $errstr, 2, STREAM_CLIENT_CONNECT, $stream);
+ if ( $read_stream === false ) {
+ return false;
+ } else {
+ $context = stream_context_get_params($read_stream);
+ $context_meta = stream_context_get_options($read_stream)['ssl']['session_meta'];
+ $cert_data = openssl_x509_parse($context["options"]["ssl"]["peer_certificate"])[0];
- if ($context_meta) {
- ?>
- <section id="conndata">
- <h3>Connection Data</h3>
- <table class="table table-striped table-bordered">
- <tbody>
- <tr>
- <td colspan="2"><strong>Connection Data</strong></td>
- </tr>
- <?php
- if ( $chain ) {
- ?>
+ if ($context_meta) {
+ ?>
+ <section id="conndata">
+ <h3>Connection Data</h3>
+ <table class="table table-striped table-bordered">
+ <tbody>
<tr>
- <td>Chain sent by Server (in server order)</td>
- <td style="font-family: monospace;">
- <?php
- $chain_length = count($chain);
- $certificate_chain = array();
- if ($chain_length <= 10) {
- for ($i = 0; $i < $chain_length; $i++) {
- if (openssl_x509_parse($chain[$i])['issuer']['CN'] && openssl_x509_parse($chain[$i])['subject']['CN']) {
- echo "Name...........: <i>";
- echo htmlspecialchars(openssl_x509_parse($chain[$i])['subject']['CN']);
- echo " </i><br>Issued by......:<i> ";
- echo htmlspecialchars(openssl_x509_parse($chain[$i])['issuer']['CN']);
- echo "</i><br>";
-
- $export_pem = "";
- openssl_x509_export($chain[$i], $export_pem);
- array_push($certificate_chain, $export_pem);
-
- if (openssl_x509_parse($chain[$i])['issuer']['CN'] == openssl_x509_parse($chain[$i + 1])['subject']['CN']){
- continue;
- } else {
- if ($i != $chain_length - 1) {
- echo "<span class='text-danger glyphicon glyphicon-remove'></span> - <span class='text-danger'>Error: Issuer does not match the next certificate CN. Chain order is probaby wrong.</span><br><br>";
+ <td colspan="2"><strong>Connection Data</strong></td>
+ </tr>
+ <?php
+ if ( $chain ) {
+ ?>
+ <tr>
+ <td>Chain sent by Server (in server order)</td>
+ <td style="font-family: monospace;">
+ <?php
+ $chain_length = count($chain);
+ $certificate_chain = array();
+ if ($chain_length <= 10) {
+ for ($i = 0; $i < $chain_length; $i++) {
+ if (openssl_x509_parse($chain[$i])['issuer']['CN'] && openssl_x509_parse($chain[$i])['subject']['CN']) {
+ echo "Name...........: <i>";
+ echo htmlspecialchars(openssl_x509_parse($chain[$i])['subject']['CN']);
+ echo " </i><br>Issued by......:<i> ";
+ echo htmlspecialchars(openssl_x509_parse($chain[$i])['issuer']['CN']);
+ echo "</i><br>";
+
+ $export_pem = "";
+ openssl_x509_export($chain[$i], $export_pem);
+ array_push($certificate_chain, $export_pem);
+
+ if (openssl_x509_parse($chain[$i])['issuer']['CN'] == openssl_x509_parse($chain[$i + 1])['subject']['CN']){
+ continue;
+ } else {
+ if ($i != $chain_length - 1) {
+ echo "<span class='text-danger glyphicon glyphicon-remove'></span> - <span class='text-danger'>Error: Issuer does not match the next certificate CN. Chain order is probaby wrong.</span><br><br>";
+ }
}
}
}
+ echo "<br>";
+ } else {
+ echo "<span class='text-danger'>Error: Certificate chain to large.</span><br>";
}
- echo "<br>";
- } else {
- echo "<span class='text-danger'>Error: Certificate chain to large.</span><br>";
- }
- file_put_contents('/tmp/verify_cert.' . $random_blurp . '.pem', implode("\n", array_reverse($certificate_chain)).PHP_EOL , FILE_APPEND);
+ file_put_contents('/tmp/verify_cert.' . $random_blurp . '.pem', implode("\n", array_reverse($certificate_chain)).PHP_EOL , FILE_APPEND);
- $verify_output = 0;
- $verify_exit_code = 0;
- $verify_exec = exec(escapeshellcmd('openssl verify -verbose -purpose any -CAfile ' . getcwd() . '/cacert.pem /tmp/verify_cert.' . $random_blurp . '.pem') . "| grep -v OK", $verify_output, $verify_exit_code);
+ $verify_output = 0;
+ $verify_exit_code = 0;
+ $verify_exec = exec(escapeshellcmd('openssl verify -verbose -purpose any -CAfile ' . getcwd() . '/cacert.pem /tmp/verify_cert.' . $random_blurp . '.pem') . "| grep -v OK", $verify_output, $verify_exit_code);
- if ($verify_exit_code != 1) {
- echo "<span class='text-danger glyphicon glyphicon-remove'></span> - <span class='text-danger'>Error: Validating certificate chain failed:</span><br>";
- echo "<pre>";
- echo str_replace('/tmp/verify_cert.' . $random_blurp . '.pem: ', '', implode("\n", $verify_output));
- echo "</pre>";
- } else {
- echo "<span class='text-success glyphicon glyphicon-ok'></span> - <span class='text-success'>Sucessfully validated certificate chain.</span><br>";
- }
+ if ($verify_exit_code != 1) {
+ echo "<span class='text-danger glyphicon glyphicon-remove'></span> - <span class='text-danger'>Error: Validating certificate chain failed:</span><br>";
+ echo "<pre>";
+ echo str_replace('/tmp/verify_cert.' . $random_blurp . '.pem: ', '', implode("\n", $verify_output));
+ echo "</pre>";
+ } else {
+ echo "<span class='text-success glyphicon glyphicon-ok'></span> - <span class='text-success'>Sucessfully validated certificate chain.</span><br>";
+ }
+
+ unlink('/tmp/verify_cert.' . $random_blurp . '.pem');
- unlink('/tmp/verify_cert.' . $random_blurp . '.pem');
+ ?>
+ </td>
+ </tr>
- ?>
+ <?php
+ }
+ if ( fixed_gethostbyname($host) ) {
+ ?>
+ <tr>
+ <td>IP / Hostname / Port</td>
+ <td>
+ <?php
+ echo htmlspecialchars(fixed_gethostbyname($host));
+ echo " - ";
+ echo htmlspecialchars(gethostbyaddr(fixed_gethostbyname($host)));
+ echo " - ";
+ echo htmlspecialchars($port);
+ ?>
</td>
</tr>
-
- <?php
- }
- if ( fixed_gethostbyname($host) ) {
- ?>
- <tr>
- <td>IP / Hostname / Port</td>
- <td>
- <?php
- echo htmlspecialchars(fixed_gethostbyname($host));
- echo " - ";
- echo htmlspecialchars(gethostbyaddr(fixed_gethostbyname($host)));
- echo " - ";
- echo htmlspecialchars($port);
- ?>
- </td>
- </tr>
- <?php
- }
- ?>
- <tr>
- <td>Protocol</td>
- <td>
- <?php
- $protocols = ssl_conn_protocols($host, $port);
- foreach (array_reverse($protocols) as $key => $value) {
- if ( $value == true ) {
- if ( $key == "tlsv1.2") {
- echo '<p><span class="text-success glyphicon glyphicon-ok"></span> - <span class="text-success">TLSv1.2 (Supported)</span></p>';
- } else if ( $key == "tlsv1.1") {
- echo '<p><span class="glyphicon glyphicon-ok"></span> - TLSv1.1 (Supported)</p>';
- } else if ( $key == "tlsv1.0") {
- echo '<p><span class="glyphicon glyphicon-ok"></span> - TLSv1.0 (Supported)</p>';
- } else if ( $key == "sslv3") {
- echo '<p><span class="text-danger glyphicon glyphicon-ok"></span> - <span class="text-danger">SSLv3 (Supported)</span></p>';
- } else {
- echo '<p><span class="glyphicon glyphicon-ok"></span> - <span>'.$key.' (Supported)</span></p>';
- }
- } else {
- if ( $key == "tlsv1.2") {
- echo '<p><span class="text-danger glyphicon glyphicon-remove"></span> - <span class="text-danger">TLSv1.2 (Not supported)</span></p>';
- } else if ( $key == "tlsv1.1") {
- echo '<p><span class="glyphicon glyphicon-remove"></span> - TLSv1.1 (Not supported)</p>';
- } else if ( $key == "tlsv1.0") {
- echo '<p><span class="glyphicon glyphicon-remove"></span> - TLSv1.0 (Not supported)</p>';
- } else if ( $key == "sslv3") {
- echo '<p><span class="text-success glyphicon glyphicon-remove"></span> - <span class="text-success">SSLv3 (Not supported)</span></p>';
+ <?php
+ }
+ ?>
+ <tr>
+ <td>Protocol</td>
+ <td>
+ <?php
+ $protocols = ssl_conn_protocols($host, $port);
+ foreach (array_reverse($protocols) as $key => $value) {
+ if ( $value == true ) {
+ if ( $key == "tlsv1.2") {
+ echo '<p><span class="text-success glyphicon glyphicon-ok"></span> - <span class="text-success">TLSv1.2 (Supported)</span></p>';
+ } else if ( $key == "tlsv1.1") {
+ echo '<p><span class="glyphicon glyphicon-ok"></span> - TLSv1.1 (Supported)</p>';
+ } else if ( $key == "tlsv1.0") {
+ echo '<p><span class="glyphicon glyphicon-ok"></span> - TLSv1.0 (Supported)</p>';
+ } else if ( $key == "sslv3") {
+ echo '<p><span class="text-danger glyphicon glyphicon-ok"></span> - <span class="text-danger">SSLv3 (Supported)</span></p>';
+ } else {
+ echo '<p><span class="glyphicon glyphicon-ok"></span> - <span>'.$key.' (Supported)</span></p>';
+ }
} else {
- echo '<p><span class="glyphicon glyphicon-remove"></span> - <span>'.$key.'(Not supported)</span></p>';
+ if ( $key == "tlsv1.2") {
+ echo '<p><span class="text-danger glyphicon glyphicon-remove"></span> - <span class="text-danger">TLSv1.2 (Not supported)</span></p>';
+ } else if ( $key == "tlsv1.1") {
+ echo '<p><span class="glyphicon glyphicon-remove"></span> - TLSv1.1 (Not supported)</p>';
+ } else if ( $key == "tlsv1.0") {
+ echo '<p><span class="glyphicon glyphicon-remove"></span> - TLSv1.0 (Not supported)</p>';
+ } else if ( $key == "sslv3") {
+ echo '<p><span class="text-success glyphicon glyphicon-remove"></span> - <span class="text-success">SSLv3 (Not supported)</span></p>';
+ } else {
+ echo '<p><span class="glyphicon glyphicon-remove"></span> - <span>'.$key.'(Not supported)</span></p>';
+ }
}
}
- }
- ?>
+ ?>
- </td>
- </tr>
- <?php
- if ($_GET['ciphersuites'] == 1) {
- ?>
- <tr>
- <td>Ciphersuites supported by server</td>
- <td>
- <?php
- $ciphersuites_to_test = array('ECDHE-RSA-AES256-GCM-SHA384',
- 'ECDHE-ECDSA-AES256-GCM-SHA384',
- 'ECDHE-RSA-AES256-SHA384',
- 'ECDHE-ECDSA-AES256-SHA384',
- 'ECDHE-RSA-AES256-SHA',
- 'ECDHE-ECDSA-AES256-SHA',
- 'SRP-DSS-AES-256-CBC-SHA',
- 'SRP-RSA-AES-256-CBC-SHA',
- 'SRP-AES-256-CBC-SHA',
- 'DH-DSS-AES256-GCM-SHA384',
- 'DHE-DSS-AES256-GCM-SHA384',
- 'DH-RSA-AES256-GCM-SHA384',
- 'DHE-RSA-AES256-GCM-SHA384',
- 'DHE-RSA-AES256-SHA256',
- 'DHE-DSS-AES256-SHA256',
- 'DH-RSA-AES256-SHA256',
- 'DH-DSS-AES256-SHA256',
- 'DHE-RSA-AES256-SHA',
- 'DHE-DSS-AES256-SHA',
- 'DH-RSA-AES256-SHA',
- 'DH-DSS-AES256-SHA',
- 'DHE-RSA-CAMELLIA256-SHA',
- 'DHE-DSS-CAMELLIA256-SHA',
- 'DH-RSA-CAMELLIA256-SHA',
- 'DH-DSS-CAMELLIA256-SHA',
- 'ECDH-RSA-AES256-GCM-SHA384',
- 'ECDH-ECDSA-AES256-GCM-SHA384',
- 'ECDH-RSA-AES256-SHA384',
- 'ECDH-ECDSA-AES256-SHA384',
- 'ECDH-RSA-AES256-SHA',
- 'ECDH-ECDSA-AES256-SHA',
- 'AES256-GCM-SHA384',
- 'AES256-SHA256',
- 'AES256-SHA',
- 'CAMELLIA256-SHA',
- 'PSK-AES256-CBC-SHA',
- 'ECDHE-RSA-AES128-GCM-SHA256',
- 'ECDHE-ECDSA-AES128-GCM-SHA256',
- 'ECDHE-RSA-AES128-SHA256',
- 'ECDHE-ECDSA-AES128-SHA256',
- 'ECDHE-RSA-AES128-SHA',
- 'ECDHE-ECDSA-AES128-SHA',
- 'SRP-DSS-AES-128-CBC-SHA',
- 'SRP-RSA-AES-128-CBC-SHA',
- 'SRP-AES-128-CBC-SHA',
- 'DH-DSS-AES128-GCM-SHA256',
- 'DHE-DSS-AES128-GCM-SHA256',
- 'DH-RSA-AES128-GCM-SHA256',
- 'DHE-RSA-AES128-GCM-SHA256',
- 'DHE-RSA-AES128-SHA256',
- 'DHE-DSS-AES128-SHA256',
- 'DH-RSA-AES128-SHA256',
- 'DH-DSS-AES128-SHA256',
- 'DHE-RSA-AES128-SHA',
- 'DHE-DSS-AES128-SHA',
- 'DH-RSA-AES128-SHA',
- 'DH-DSS-AES128-SHA',
- 'DHE-RSA-SEED-SHA',
- 'DHE-DSS-SEED-SHA',
- 'DH-RSA-SEED-SHA',
- 'DH-DSS-SEED-SHA',
- 'DHE-RSA-CAMELLIA128-SHA',
- 'DHE-DSS-CAMELLIA128-SHA',
- 'DH-RSA-CAMELLIA128-SHA',
- 'DH-DSS-CAMELLIA128-SHA',
- 'ECDH-RSA-AES128-GCM-SHA256',
- 'ECDH-ECDSA-AES128-GCM-SHA256',
- 'ECDH-RSA-AES128-SHA256',
- 'ECDH-ECDSA-AES128-SHA256',
- 'ECDH-RSA-AES128-SHA',
- 'ECDH-ECDSA-AES128-SHA',
- 'AES128-GCM-SHA256',
- 'AES128-SHA256',
- 'AES128-SHA',
- 'SEED-SHA',
- 'CAMELLIA128-SHA',
- 'IDEA-CBC-SHA',
- 'PSK-AES128-CBC-SHA',
- 'ECDHE-RSA-RC4-SHA',
- 'ECDHE-ECDSA-RC4-SHA',
- 'ECDH-RSA-RC4-SHA',
- 'ECDH-ECDSA-RC4-SHA',
- 'RC4-SHA',
- 'RC4-MD5',
- 'PSK-RC4-SHA',
- 'ECDHE-RSA-DES-CBC3-SHA',
- 'ECDHE-ECDSA-DES-CBC3-SHA',
- 'SRP-DSS-3DES-EDE-CBC-SHA',
- 'SRP-RSA-3DES-EDE-CBC-SHA',
- 'SRP-3DES-EDE-CBC-SHA',
- 'EDH-RSA-DES-CBC3-SHA',
- 'EDH-DSS-DES-CBC3-SHA',
- 'DH-RSA-DES-CBC3-SHA',
- 'DH-DSS-DES-CBC3-SHA',
- 'ECDH-RSA-DES-CBC3-SHA',
- 'ECDH-ECDSA-DES-CBC3-SHA',
- 'DES-CBC3-SHA',
- 'PSK-3DES-EDE-CBC-SHA',
- 'EDH-RSA-DES-CBC-SHA',
- 'EDH-DSS-DES-CBC-SHA',
- 'DH-RSA-DES-CBC-SHA',
- 'DH-DSS-DES-CBC-SHA',
- 'DES-CBC-SHA',
- 'EXP-EDH-RSA-DES-CBC-SHA',
- 'EXP-EDH-DSS-DES-CBC-SHA',
- 'EXP-DH-RSA-DES-CBC-SHA',
- 'EXP-DH-DSS-DES-CBC-SHA',
- 'EXP-DES-CBC-SHA',
- 'EXP-RC2-CBC-MD5',
- 'EXP-RC4-MD5',
- 'ECDHE-RSA-NULL-SHA',
- 'ECDHE-ECDSA-NULL-SHA',
- 'AECDH-NULL-SHA',
- 'ECDH-RSA-NULL-SHA',
- 'ECDH-ECDSA-NULL-SHA',
- 'NULL-SHA256',
- 'NULL-SHA',
- 'NULL-MD5');
-
- $bad_ciphersuites = array('ECDHE-RSA-DES-CBC3-SHA',
- 'ECDHE-ECDSA-DES-CBC3-SHA',
- 'EDH-RSA-DES-CBC3-SHA',
- 'EDH-DSS-DES-CBC3-SHA',
- 'DH-RSA-DES-CBC3-SHA',
- 'DH-DSS-DES-CBC3-SHA',
- 'ECDH-RSA-DES-CBC3-SHA',
- 'ECDH-ECDSA-DES-CBC3-SHA',
- 'DES-CBC3-SHA',
- 'EDH-RSA-DES-CBC-SHA',
- 'EDH-DSS-DES-CBC-SHA',
- 'DH-RSA-DES-CBC-SHA',
- 'DH-DSS-DES-CBC-SHA',
- 'DES-CBC-SHA',
- 'EXP-EDH-RSA-DES-CBC-SHA',
- 'EXP-EDH-DSS-DES-CBC-SHA',
- 'EXP-DH-RSA-DES-CBC-SHA',
- 'EXP-DH-DSS-DES-CBC-SHA',
- 'EXP-DES-CBC-SHA',
- 'EXP-EDH-RSA-DES-CBC-SHA',
- 'EXP-EDH-DSS-DES-CBC-SHA',
- 'EXP-DH-RSA-DES-CBC-SHA',
- 'EXP-DH-DSS-DES-CBC-SHA',
- 'EXP-DES-CBC-SHA',
- 'EXP-RC2-CBC-MD5',
- 'EXP-RC4-MD5',
- 'RC4-MD5',
- 'EXP-RC2-CBC-MD5',
- 'EXP-RC4-MD5',
- 'ECDHE-RSA-RC4-SHA',
- 'ECDHE-ECDSA-RC4-SHA',
- 'ECDH-RSA-RC4-SHA',
- 'ECDH-ECDSA-RC4-SHA',
- 'RC4-SHA',
- 'RC4-MD5',
- 'PSK-RC4-SHA',
- 'EXP-RC4-MD5',
- 'ECDHE-RSA-NULL-SHA',
- 'ECDHE-ECDSA-NULL-SHA',
- 'AECDH-NULL-SHA',
- 'RC4-SHA',
- 'RC4-MD5',
- 'ECDH-RSA-NULL-SHA',
- 'ECDH-ECDSA-NULL-SHA',
- 'NULL-SHA256',
- 'NULL-SHA',
- 'NULL-MD5');
- $supported_ciphersuites = ssl_conn_ciphersuites($host, $port, $ciphersuites_to_test);
-
- foreach ($supported_ciphersuites as $key => $value) {
- if($value == true){
- if (in_array($key, $bad_ciphersuites)) {
- $bad_ciphersuite = 1;
- echo "";
- echo "<span class='text-danger glyphicon glyphicon-remove'></span> ";
+ </td>
+ </tr>
+ <?php
+ if ($_GET['ciphersuites'] == 1) {
+ ?>
+ <tr>
+ <td>Ciphersuites supported by server</td>
+ <td>
+ <?php
+ $ciphersuites_to_test = array('ECDHE-RSA-AES256-GCM-SHA384',
+ 'ECDHE-ECDSA-AES256-GCM-SHA384',
+ 'ECDHE-RSA-AES256-SHA384',
+ 'ECDHE-ECDSA-AES256-SHA384',
+ 'ECDHE-RSA-AES256-SHA',
+ 'ECDHE-ECDSA-AES256-SHA',
+ 'SRP-DSS-AES-256-CBC-SHA',
+ 'SRP-RSA-AES-256-CBC-SHA',
+ 'SRP-AES-256-CBC-SHA',
+ 'DH-DSS-AES256-GCM-SHA384',
+ 'DHE-DSS-AES256-GCM-SHA384',
+ 'DH-RSA-AES256-GCM-SHA384',
+ 'DHE-RSA-AES256-GCM-SHA384',
+ 'DHE-RSA-AES256-SHA256',
+ 'DHE-DSS-AES256-SHA256',
+ 'DH-RSA-AES256-SHA256',
+ 'DH-DSS-AES256-SHA256',
+ 'DHE-RSA-AES256-SHA',
+ 'DHE-DSS-AES256-SHA',
+ 'DH-RSA-AES256-SHA',
+ 'DH-DSS-AES256-SHA',
+ 'DHE-RSA-CAMELLIA256-SHA',
+ 'DHE-DSS-CAMELLIA256-SHA',
+ 'DH-RSA-CAMELLIA256-SHA',
+ 'DH-DSS-CAMELLIA256-SHA',
+ 'ECDH-RSA-AES256-GCM-SHA384',
+ 'ECDH-ECDSA-AES256-GCM-SHA384',
+ 'ECDH-RSA-AES256-SHA384',
+ 'ECDH-ECDSA-AES256-SHA384',
+ 'ECDH-RSA-AES256-SHA',
+ 'ECDH-ECDSA-AES256-SHA',
+ 'AES256-GCM-SHA384',
+ 'AES256-SHA256',
+ 'AES256-SHA',
+ 'CAMELLIA256-SHA',
+ 'PSK-AES256-CBC-SHA',
+ 'ECDHE-RSA-AES128-GCM-SHA256',
+ 'ECDHE-ECDSA-AES128-GCM-SHA256',
+ 'ECDHE-RSA-AES128-SHA256',
+ 'ECDHE-ECDSA-AES128-SHA256',
+ 'ECDHE-RSA-AES128-SHA',
+ 'ECDHE-ECDSA-AES128-SHA',
+ 'SRP-DSS-AES-128-CBC-SHA',
+ 'SRP-RSA-AES-128-CBC-SHA',
+ 'SRP-AES-128-CBC-SHA',
+ 'DH-DSS-AES128-GCM-SHA256',
+ 'DHE-DSS-AES128-GCM-SHA256',
+ 'DH-RSA-AES128-GCM-SHA256',
+ 'DHE-RSA-AES128-GCM-SHA256',
+ 'DHE-RSA-AES128-SHA256',
+ 'DHE-DSS-AES128-SHA256',
+ 'DH-RSA-AES128-SHA256',
+ 'DH-DSS-AES128-SHA256',
+ 'DHE-RSA-AES128-SHA',
+ 'DHE-DSS-AES128-SHA',
+ 'DH-RSA-AES128-SHA',
+ 'DH-DSS-AES128-SHA',
+ 'DHE-RSA-SEED-SHA',
+ 'DHE-DSS-SEED-SHA',
+ 'DH-RSA-SEED-SHA',
+ 'DH-DSS-SEED-SHA',
+ 'DHE-RSA-CAMELLIA128-SHA',
+ 'DHE-DSS-CAMELLIA128-SHA',
+ 'DH-RSA-CAMELLIA128-SHA',
+ 'DH-DSS-CAMELLIA128-SHA',
+ 'ECDH-RSA-AES128-GCM-SHA256',
+ 'ECDH-ECDSA-AES128-GCM-SHA256',
+ 'ECDH-RSA-AES128-SHA256',
+ 'ECDH-ECDSA-AES128-SHA256',
+ 'ECDH-RSA-AES128-SHA',
+ 'ECDH-ECDSA-AES128-SHA',
+ 'AES128-GCM-SHA256',
+ 'AES128-SHA256',
+ 'AES128-SHA',
+ 'SEED-SHA',
+ 'CAMELLIA128-SHA',
+ 'IDEA-CBC-SHA',
+ 'PSK-AES128-CBC-SHA',
+ 'ECDHE-RSA-RC4-SHA',
+ 'ECDHE-ECDSA-RC4-SHA',
+ 'ECDH-RSA-RC4-SHA',
+ 'ECDH-ECDSA-RC4-SHA',
+ 'RC4-SHA',
+ 'RC4-MD5',
+ 'PSK-RC4-SHA',
+ 'ECDHE-RSA-DES-CBC3-SHA',
+ 'ECDHE-ECDSA-DES-CBC3-SHA',
+ 'SRP-DSS-3DES-EDE-CBC-SHA',
+ 'SRP-RSA-3DES-EDE-CBC-SHA',
+ 'SRP-3DES-EDE-CBC-SHA',
+ 'EDH-RSA-DES-CBC3-SHA',
+ 'EDH-DSS-DES-CBC3-SHA',
+ 'DH-RSA-DES-CBC3-SHA',
+ 'DH-DSS-DES-CBC3-SHA',
+ 'ECDH-RSA-DES-CBC3-SHA',
+ 'ECDH-ECDSA-DES-CBC3-SHA',
+ 'DES-CBC3-SHA',
+ 'PSK-3DES-EDE-CBC-SHA',
+ 'EDH-RSA-DES-CBC-SHA',
+ 'EDH-DSS-DES-CBC-SHA',
+ 'DH-RSA-DES-CBC-SHA',
+ 'DH-DSS-DES-CBC-SHA',
+ 'DES-CBC-SHA',
+ 'EXP-EDH-RSA-DES-CBC-SHA',
+ 'EXP-EDH-DSS-DES-CBC-SHA',
+ 'EXP-DH-RSA-DES-CBC-SHA',
+ 'EXP-DH-DSS-DES-CBC-SHA',
+ 'EXP-DES-CBC-SHA',
+ 'EXP-RC2-CBC-MD5',
+ 'EXP-RC4-MD5',
+ 'ECDHE-RSA-NULL-SHA',
+ 'ECDHE-ECDSA-NULL-SHA',
+ 'AECDH-NULL-SHA',
+ 'ECDH-RSA-NULL-SHA',
+ 'ECDH-ECDSA-NULL-SHA',
+ 'NULL-SHA256',
+ 'NULL-SHA',
+ 'NULL-MD5');
+
+ $bad_ciphersuites = array('ECDHE-RSA-DES-CBC3-SHA',
+ 'ECDHE-ECDSA-DES-CBC3-SHA',
+ 'EDH-RSA-DES-CBC3-SHA',
+ 'EDH-DSS-DES-CBC3-SHA',
+ 'DH-RSA-DES-CBC3-SHA',
+ 'DH-DSS-DES-CBC3-SHA',
+ 'ECDH-RSA-DES-CBC3-SHA',
+ 'ECDH-ECDSA-DES-CBC3-SHA',
+ 'DES-CBC3-SHA',
+ 'EDH-RSA-DES-CBC-SHA',
+ 'EDH-DSS-DES-CBC-SHA',
+ 'DH-RSA-DES-CBC-SHA',
+ 'DH-DSS-DES-CBC-SHA',
+ 'DES-CBC-SHA',
+ 'EXP-EDH-RSA-DES-CBC-SHA',
+ 'EXP-EDH-DSS-DES-CBC-SHA',
+ 'EXP-DH-RSA-DES-CBC-SHA',
+ 'EXP-DH-DSS-DES-CBC-SHA',
+ 'EXP-DES-CBC-SHA',
+ 'EXP-EDH-RSA-DES-CBC-SHA',
+ 'EXP-EDH-DSS-DES-CBC-SHA',
+ 'EXP-DH-RSA-DES-CBC-SHA',
+ 'EXP-DH-DSS-DES-CBC-SHA',
+ 'EXP-DES-CBC-SHA',
+ 'EXP-RC2-CBC-MD5',
+ 'EXP-RC4-MD5',
+ 'RC4-MD5',
+ 'EXP-RC2-CBC-MD5',
+ 'EXP-RC4-MD5',
+ 'ECDHE-RSA-RC4-SHA',
+ 'ECDHE-ECDSA-RC4-SHA',
+ 'ECDH-RSA-RC4-SHA',
+ 'ECDH-ECDSA-RC4-SHA',
+ 'RC4-SHA',
+ 'RC4-MD5',
+ 'PSK-RC4-SHA',
+ 'EXP-RC4-MD5',
+ 'ECDHE-RSA-NULL-SHA',
+ 'ECDHE-ECDSA-NULL-SHA',
+ 'AECDH-NULL-SHA',
+ 'RC4-SHA',
+ 'RC4-MD5',
+ 'ECDH-RSA-NULL-SHA',
+ 'ECDH-ECDSA-NULL-SHA',
+ 'NULL-SHA256',
+ 'NULL-SHA',
+ 'NULL-MD5');
+ $supported_ciphersuites = ssl_conn_ciphersuites($host, $port, $ciphersuites_to_test);
+
+ foreach ($supported_ciphersuites as $key => $value) {
+ if($value == true){
+ if (in_array($key, $bad_ciphersuites)) {
+ $bad_ciphersuite = 1;
+ echo "";
+ echo "<span class='text-danger glyphicon glyphicon-remove'></span> ";
+ } else {
+ echo "<span class='glyphicon glyphicon-minus'></span> ";
+ }
+ echo htmlspecialchars($key);
+ echo "<br>";
} else {
- echo "<span class='glyphicon glyphicon-minus'></span> ";
+ echo "<!-- ";
+ echo "<span class='glyphicon glyphicon-remove'></span> - ";
+ echo htmlspecialchars($key);
+ echo " <br -->";
}
- echo htmlspecialchars($key);
- echo "<br>";
- } else {
- echo "<!-- ";
- echo "<span class='glyphicon glyphicon-remove'></span> - ";
- echo htmlspecialchars($key);
- echo " <br -->";
}
- }
- if ($bad_ciphersuite) {
- ?>
- <p><br>Ciphersuites containing <a href="https://en.wikipedia.org/wiki/Null_cipher">NULL</a>, <a href="https://en.wikipedia.org/wiki/Export_of_cryptography_from_the_United_States">EXP(ort)</a>, <a href="https://en.wikipedia.org/wiki/Weak_key">DES and RC4</a> are marked RED because they are suboptimal.</p>
- <?php
- }
-
- ?>
- </td>
- </tr>
- <?php
- } else {
- ?>
- <tr>
- <td>Ciphersuite</td>
- <td>
- <?php
- echo htmlspecialchars($context_meta['cipher_name']);
- echo " (".htmlspecialchars($context_meta['cipher_bits'])." bits)";
- ?>
- </td>
- </tr>
- <?php
- }
- ?>
- <tr>
- <td>
- <a href="http://googleonlinesecurity.blogspot.nl/2014/10/this-poodle-bites-exploiting-ssl-30.html">TLS_FALLBACK_SCSV</a>
+ if ($bad_ciphersuite) {
+ ?>
+ <p><br>Ciphersuites containing <a href="https://en.wikipedia.org/wiki/Null_cipher">NULL</a>, <a href="https://en.wikipedia.org/wiki/Export_of_cryptography_from_the_United_States">EXP(ort)</a>, <a href="https://en.wikipedia.org/wiki/Weak_key">DES and RC4</a> are marked RED because they are suboptimal.</p>
+ <?php
+ }
+
+ ?>
</td>
- <td>
+ </tr>
<?php
- $fallback = tls_fallback_scsv($host, $port);
- // echo "<pre>";
- // var_dump($fallback);
- // echo "</pre>";
- if ($fallback['protocol_count'] == 1) {
- echo "Only 1 protocol enabled, fallback not possible, TLS_FALLBACK_SCSV not required.";
} else {
- if ($fallback['tls_fallback_scsv_support'] == 1) {
- echo "<span class='text-success glyphicon glyphicon-ok'></span> - <span class='text-success'>TLS_FALLBACK_SCSV supported.</span>";
- } else {
- echo "<span class='text-danger glyphicon glyphicon-remove'></span> - <span class='text-danger'>TLS_FALLBACK_SCSV not supported.</span>";
- }
+ ?>
+ <tr>
+ <td>Ciphersuite</td>
+ <td>
+ <?php
+ echo htmlspecialchars($context_meta['cipher_name']);
+ echo " (".htmlspecialchars($context_meta['cipher_bits'])." bits)";
+ ?>
+ </td>
+ </tr>
+ <?php
}
?>
- </td>
- </tr>
- <?php
- $headers = server_http_headers($host, $port);
- ?>
- <tr>
- <td><a href="https://raymii.org/s/tutorials/HTTP_Strict_Transport_Security_for_Apache_NGINX_and_Lighttpd.html">Strict Transport Security</a></td>
- <td>
- <?php
- if ( $headers["strict-transport-security"] ) {
- echo "<span class='text-success glyphicon glyphicon-ok'></span> - <span class='text-success'>";
- if ( is_array($headers["strict-transport-security"])) {
- echo htmlspecialchars(substr($headers["strict-transport-security"][0], 0, 50));
- echo "<br > <i>HSTS header was found multiple times. Only showing the first one.</i>";
+ <tr>
+ <td>
+ <a href="http://googleonlinesecurity.blogspot.nl/2014/10/this-poodle-bites-exploiting-ssl-30.html">TLS_FALLBACK_SCSV</a>
+ </td>
+ <td>
+ <?php
+ $fallback = tls_fallback_scsv($host, $port);
+ // echo "<pre>";
+ // var_dump($fallback);
+ // echo "</pre>";
+ if ($fallback['protocol_count'] == 1) {
+ echo "Only 1 protocol enabled, fallback not possible, TLS_FALLBACK_SCSV not required.";
} else {
- echo htmlspecialchars(substr($headers["strict-transport-security"], 0, 50));
+ if ($fallback['tls_fallback_scsv_support'] == 1) {
+ echo "<span class='text-success glyphicon glyphicon-ok'></span> - <span class='text-success'>TLS_FALLBACK_SCSV supported.</span>";
+ } else {
+ echo "<span class='text-danger glyphicon glyphicon-remove'></span> - <span class='text-danger'>TLS_FALLBACK_SCSV not supported.</span>";
+ }
}
- echo "</span>";
- } else {
- echo '<span class="text-danger glyphicon glyphicon-remove"></span> - <span class="text-danger">Not Set</span>';
- }
?>
- </td>
- </tr>
- <tr>
- <td><a href="https://raymii.org/s/articles/HTTP_Public_Key_Pinning_Extension_HPKP.html">HTTP Public Key Pinning Extension (HPKP)</a></td>
- <td>
- <?php
- if ( $headers["public-key-pins"] ) {
- echo "<span class='text-success glyphicon glyphicon-ok'></span> - <span class='text-success'>";
- if ( is_array($headers["public-key-pins"])) {
- echo htmlspecialchars(substr($headers["public-key-pins"][0], 0, 255));
- echo "<br > <i>HPKP header was found multiple times. Only showing the first one.</i>";
- echo "</span>";
+ </td>
+ </tr>
+ <?php
+ $headers = server_http_headers($host, $port);
+ ?>
+ <tr>
+ <td><a href="https://raymii.org/s/tutorials/HTTP_Strict_Transport_Security_for_Apache_NGINX_and_Lighttpd.html">Strict Transport Security</a></td>
+ <td>
+ <?php
+ if ( $headers["strict-transport-security"] ) {
+ echo "<span class='text-success glyphicon glyphicon-ok'></span> - <span class='text-success'>";
+ if ( is_array($headers["strict-transport-security"])) {
+ echo htmlspecialchars(substr($headers["strict-transport-security"][0], 0, 50));
+ echo "<br > <i>HSTS header was found multiple times. Only showing the first one.</i>";
+ } else {
+ echo htmlspecialchars(substr($headers["strict-transport-security"], 0, 50));
+ }
+ echo "</span>";
} else {
- echo htmlspecialchars(substr($headers["public-key-pins"], 0, 255));
+ echo '<span class="text-danger glyphicon glyphicon-remove"></span> - <span class="text-danger">Not Set</span>';
}
- } else {
- echo '<span>Not Set</span>';
- }
- ?>
- <?php
- if ( $headers["public-key-pins-report-only"] ) {
- echo "<b>Report Only</b>: ";
- if ( is_array($headers["public-key-pins-report-only"])) {
- echo htmlspecialchars(substr($headers["public-key-pins-report-only"][0], 0, 255));
- echo "<br > <i>HPKP Report Only header was found multiple times. Only showing the first one.</i>";
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td><a href="https://raymii.org/s/articles/HTTP_Public_Key_Pinning_Extension_HPKP.html">HTTP Public Key Pinning Extension (HPKP)</a></td>
+ <td>
+ <?php
+ if ( $headers["public-key-pins"] ) {
+ echo "<span class='text-success glyphicon glyphicon-ok'></span> - <span class='text-success'>";
+ if ( is_array($headers["public-key-pins"])) {
+ echo htmlspecialchars(substr($headers["public-key-pins"][0], 0, 255));
+ echo "<br > <i>HPKP header was found multiple times. Only showing the first one.</i>";
+ echo "</span>";
+ } else {
+ echo htmlspecialchars(substr($headers["public-key-pins"], 0, 255));
+ }
} else {
- echo htmlspecialchars(substr($headers["public-key-pins-report-only"], 0, 255));
+ echo '<span>Not Set</span>';
}
- }
- ?>
- </td>
- </tr>
- <tr>
- <td>OCSP Stapling</td>
- <td>
- <?php
- $stapling = ocsp_stapling($host,$port);
- if($stapling["working"] == 1) {
- echo "<table class='table'>";
- foreach ($stapling as $key => $value) {
- if ($key != "working") {
- echo "<tr><td>" . $key . "</td><td>" . $value . "</td></tr>";
+ ?>
+ <?php
+ if ( $headers["public-key-pins-report-only"] ) {
+ echo "<b>Report Only</b>: ";
+ if ( is_array($headers["public-key-pins-report-only"])) {
+ echo htmlspecialchars(substr($headers["public-key-pins-report-only"][0], 0, 255));
+ echo "<br > <i>HPKP Report Only header was found multiple times. Only showing the first one.</i>";
+ } else {
+ echo htmlspecialchars(substr($headers["public-key-pins-report-only"], 0, 255));
}
}
- echo "</table>";
- } else {
- echo "No response received.";
- }
- ?>
- </td>
- </tr>
- <tr>
- <td>This Server' OpenSSL Version</td>
- <td>
- <?php
- echo htmlspecialchars(shell_exec("openssl version"));
- ?>
- </td>
- </tr>
- <tr>
- <td>This Server' Date (RFC 2822)</td>
- <td>
- <?php
- echo htmlspecialchars(shell_exec("date --rfc-2822"));
- ?>
- </td>
- </tr>
- </tbody>
- </table>
- </section>
- <?php
- } else {
- return false;
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td>OCSP Stapling</td>
+ <td>
+ <?php
+ $stapling = ocsp_stapling($host,$port);
+ if($stapling["working"] == 1) {
+ echo "<table class='table'>";
+ foreach ($stapling as $key => $value) {
+ if ($key != "working") {
+ echo "<tr><td>" . $key . "</td><td>" . $value . "</td></tr>";
+ }
+ }
+ echo "</table>";
+ } else {
+ echo "No response received.";
+ }
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td>This Server' OpenSSL Version</td>
+ <td>
+ <?php
+ echo htmlspecialchars(shell_exec("openssl version"));
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td>This Server' Date (RFC 2822)</td>
+ <td>
+ <?php
+ echo htmlspecialchars(shell_exec("date --rfc-2822"));
+ ?>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </section>
+ <?php
+ } else {
+ return false;
+ }
}
}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+function ssl_conn_metadata_json($host, $port, $read_stream, $chain_data=null) {
+ $result = array();
+ global $random_blurp;
+ global $current_folder;
+ $context = stream_context_get_params($read_stream);
+ $context_meta = stream_context_get_options($read_stream)['ssl']['session_meta'];
+ $cert_data = openssl_x509_parse($context["options"]["ssl"]["peer_certificate"])[0];
+ //chain
+ if (isset($context_meta)) {
+ if (isset($chain_data)) {
+
+ $chain_length = count($chain_data);
+ $certificate_chain = array();
+ if ($chain_length <= 10) {
+ for ($i = 0; $i < $chain_length; $i++) {
+ if (openssl_x509_parse($chain_data[$i])['issuer']['CN'] && openssl_x509_parse($chain_data[$i])['subject']['CN']) {
+ $result["chain"][$i]["name"] = openssl_x509_parse($chain_data[$i])['subject']['CN'];
+ $result["chain"][$i]["issuer"] = openssl_x509_parse($chain_data[$i])['issuer']['CN'];
+ $export_pem = "";
+ openssl_x509_export($chain_data[$i], $export_pem);
+ array_push($certificate_chain, $export_pem);
+ if (openssl_x509_parse($chain_data[$i])['issuer']['CN'] == openssl_x509_parse($chain_data[$i + 1])['subject']['CN']){
+ continue;
+ } else {
+ if ($i != $chain_length - 1) {
+ $result["chain"][$i]["error"] = "Issuer does not match the next certificate CN. Chain order is probaby wrong.";
+ }
+ }
+ }
+ }
+ }
+ // chain validation
+ file_put_contents('/tmp/verify_cert.' . $random_blurp . '.pem', implode("\n", array_reverse($certificate_chain)).PHP_EOL , FILE_APPEND);
+ $verify_output = 0;
+ $verify_exit_code = 0;
+ $verify_exec = exec(escapeshellcmd('openssl verify -verbose -purpose any -CAfile ' . getcwd() . '/cacert.pem /tmp/verify_cert.' . $random_blurp . '.pem') . "| grep -v OK", $verify_output, $verify_exit_code);
+
+ if ($verify_exit_code != 1) {
+ $result["chain"]["validation"]["status"] = "failed";
+ $result["chain"]["validation"]["error"] = "Error: Validating certificate chain failed: " . str_replace('/tmp/verify_cert.' . $random_blurp . '.pem: ', '', implode("\n", $verify_output));
+ } else {
+ $result["chain"]["validation"]["status"] = "success";
+ }
+ unlink('/tmp/verify_cert.' . $random_blurp . '.pem');
+ }
+ // hostname ip port
+ if (fixed_gethostbyname($host)) {
+ $result["ip"] = fixed_gethostbyname($host);
+ $result["hostname"] = gethostbyaddr(fixed_gethostbyname($host));
+ $result["port"] = $port;
+ }
+
+ // protocols
+ $result["protocols"] = array_reverse(ssl_conn_protocols($host, $port));
+
+ // ciphersuites
+ if ($_GET['ciphersuites'] == 1) {
+ $ciphersuites_to_test = array('ECDHE-RSA-AES256-GCM-SHA384',
+ 'ECDHE-ECDSA-AES256-GCM-SHA384',
+ 'ECDHE-RSA-AES256-SHA384',
+ 'ECDHE-ECDSA-AES256-SHA384',
+ 'ECDHE-RSA-AES256-SHA',
+ 'ECDHE-ECDSA-AES256-SHA',
+ 'SRP-DSS-AES-256-CBC-SHA',
+ 'SRP-RSA-AES-256-CBC-SHA',
+ 'SRP-AES-256-CBC-SHA',
+ 'DH-DSS-AES256-GCM-SHA384',
+ 'DHE-DSS-AES256-GCM-SHA384',
+ 'DH-RSA-AES256-GCM-SHA384',
+ 'DHE-RSA-AES256-GCM-SHA384',
+ 'DHE-RSA-AES256-SHA256',
+ 'DHE-DSS-AES256-SHA256',
+ 'DH-RSA-AES256-SHA256',
+ 'DH-DSS-AES256-SHA256',
+ 'DHE-RSA-AES256-SHA',
+ 'DHE-DSS-AES256-SHA',
+ 'DH-RSA-AES256-SHA',
+ 'DH-DSS-AES256-SHA',
+ 'DHE-RSA-CAMELLIA256-SHA',
+ 'DHE-DSS-CAMELLIA256-SHA',
+ 'DH-RSA-CAMELLIA256-SHA',
+ 'DH-DSS-CAMELLIA256-SHA',
+ 'ECDH-RSA-AES256-GCM-SHA384',
+ 'ECDH-ECDSA-AES256-GCM-SHA384',
+ 'ECDH-RSA-AES256-SHA384',
+ 'ECDH-ECDSA-AES256-SHA384',
+ 'ECDH-RSA-AES256-SHA',
+ 'ECDH-ECDSA-AES256-SHA',
+ 'AES256-GCM-SHA384',
+ 'AES256-SHA256',
+ 'AES256-SHA',
+ 'CAMELLIA256-SHA',
+ 'PSK-AES256-CBC-SHA',
+ 'ECDHE-RSA-AES128-GCM-SHA256',
+ 'ECDHE-ECDSA-AES128-GCM-SHA256',
+ 'ECDHE-RSA-AES128-SHA256',
+ 'ECDHE-ECDSA-AES128-SHA256',
+ 'ECDHE-RSA-AES128-SHA',
+ 'ECDHE-ECDSA-AES128-SHA',
+ 'SRP-DSS-AES-128-CBC-SHA',
+ 'SRP-RSA-AES-128-CBC-SHA',
+ 'SRP-AES-128-CBC-SHA',
+ 'DH-DSS-AES128-GCM-SHA256',
+ 'DHE-DSS-AES128-GCM-SHA256',
+ 'DH-RSA-AES128-GCM-SHA256',
+ 'DHE-RSA-AES128-GCM-SHA256',
+ 'DHE-RSA-AES128-SHA256',
+ 'DHE-DSS-AES128-SHA256',
+ 'DH-RSA-AES128-SHA256',
+ 'DH-DSS-AES128-SHA256',
+ 'DHE-RSA-AES128-SHA',
+ 'DHE-DSS-AES128-SHA',
+ 'DH-RSA-AES128-SHA',
+ 'DH-DSS-AES128-SHA',
+ 'DHE-RSA-SEED-SHA',
+ 'DHE-DSS-SEED-SHA',
+ 'DH-RSA-SEED-SHA',
+ 'DH-DSS-SEED-SHA',
+ 'DHE-RSA-CAMELLIA128-SHA',
+ 'DHE-DSS-CAMELLIA128-SHA',
+ 'DH-RSA-CAMELLIA128-SHA',
+ 'DH-DSS-CAMELLIA128-SHA',
+ 'ECDH-RSA-AES128-GCM-SHA256',
+ 'ECDH-ECDSA-AES128-GCM-SHA256',
+ 'ECDH-RSA-AES128-SHA256',
+ 'ECDH-ECDSA-AES128-SHA256',
+ 'ECDH-RSA-AES128-SHA',
+ 'ECDH-ECDSA-AES128-SHA',
+ 'AES128-GCM-SHA256',
+ 'AES128-SHA256',
+ 'AES128-SHA',
+ 'SEED-SHA',
+ 'CAMELLIA128-SHA',
+ 'IDEA-CBC-SHA',
+ 'PSK-AES128-CBC-SHA',
+ 'ECDHE-RSA-RC4-SHA',
+ 'ECDHE-ECDSA-RC4-SHA',
+ 'ECDH-RSA-RC4-SHA',
+ 'ECDH-ECDSA-RC4-SHA',
+ 'RC4-SHA',
+ 'RC4-MD5',
+ 'PSK-RC4-SHA',
+ 'ECDHE-RSA-DES-CBC3-SHA',
+ 'ECDHE-ECDSA-DES-CBC3-SHA',
+ 'SRP-DSS-3DES-EDE-CBC-SHA',
+ 'SRP-RSA-3DES-EDE-CBC-SHA',
+ 'SRP-3DES-EDE-CBC-SHA',
+ 'EDH-RSA-DES-CBC3-SHA',
+ 'EDH-DSS-DES-CBC3-SHA',
+ 'DH-RSA-DES-CBC3-SHA',
+ 'DH-DSS-DES-CBC3-SHA',
+ 'ECDH-RSA-DES-CBC3-SHA',
+ 'ECDH-ECDSA-DES-CBC3-SHA',
+ 'DES-CBC3-SHA',
+ 'PSK-3DES-EDE-CBC-SHA',
+ 'EDH-RSA-DES-CBC-SHA',
+ 'EDH-DSS-DES-CBC-SHA',
+ 'DH-RSA-DES-CBC-SHA',
+ 'DH-DSS-DES-CBC-SHA',
+ 'DES-CBC-SHA',
+ 'EXP-EDH-RSA-DES-CBC-SHA',
+ 'EXP-EDH-DSS-DES-CBC-SHA',
+ 'EXP-DH-RSA-DES-CBC-SHA',
+ 'EXP-DH-DSS-DES-CBC-SHA',
+ 'EXP-DES-CBC-SHA',
+ 'EXP-RC2-CBC-MD5',
+ 'EXP-RC4-MD5',
+ 'ECDHE-RSA-NULL-SHA',
+ 'ECDHE-ECDSA-NULL-SHA',
+ 'AECDH-NULL-SHA',
+ 'ECDH-RSA-NULL-SHA',
+ 'ECDH-ECDSA-NULL-SHA',
+ 'NULL-SHA256',
+ 'NULL-SHA',
+ 'NULL-MD5');
+
+ $bad_ciphersuites = array('ECDHE-RSA-DES-CBC3-SHA',
+ 'ECDHE-ECDSA-DES-CBC3-SHA',
+ 'EDH-RSA-DES-CBC3-SHA',
+ 'EDH-DSS-DES-CBC3-SHA',
+ 'DH-RSA-DES-CBC3-SHA',
+ 'DH-DSS-DES-CBC3-SHA',
+ 'ECDH-RSA-DES-CBC3-SHA',
+ 'ECDH-ECDSA-DES-CBC3-SHA',
+ 'DES-CBC3-SHA',
+ 'EDH-RSA-DES-CBC-SHA',
+ 'EDH-DSS-DES-CBC-SHA',
+ 'DH-RSA-DES-CBC-SHA',
+ 'DH-DSS-DES-CBC-SHA',
+ 'DES-CBC-SHA',
+ 'EXP-EDH-RSA-DES-CBC-SHA',
+ 'EXP-EDH-DSS-DES-CBC-SHA',
+ 'EXP-DH-RSA-DES-CBC-SHA',
+ 'EXP-DH-DSS-DES-CBC-SHA',
+ 'EXP-DES-CBC-SHA',
+ 'EXP-EDH-RSA-DES-CBC-SHA',
+ 'EXP-EDH-DSS-DES-CBC-SHA',
+ 'EXP-DH-RSA-DES-CBC-SHA',
+ 'EXP-DH-DSS-DES-CBC-SHA',
+ 'EXP-DES-CBC-SHA',
+ 'EXP-RC2-CBC-MD5',
+ 'EXP-RC4-MD5',
+ 'RC4-MD5',
+ 'EXP-RC2-CBC-MD5',
+ 'EXP-RC4-MD5',
+ 'ECDHE-RSA-RC4-SHA',
+ 'ECDHE-ECDSA-RC4-SHA',
+ 'ECDH-RSA-RC4-SHA',
+ 'ECDH-ECDSA-RC4-SHA',
+ 'RC4-SHA',
+ 'RC4-MD5',
+ 'PSK-RC4-SHA',
+ 'EXP-RC4-MD5',
+ 'ECDHE-RSA-NULL-SHA',
+ 'ECDHE-ECDSA-NULL-SHA',
+ 'AECDH-NULL-SHA',
+ 'RC4-SHA',
+ 'RC4-MD5',
+ 'ECDH-RSA-NULL-SHA',
+ 'ECDH-ECDSA-NULL-SHA',
+ 'NULL-SHA256',
+ 'NULL-SHA',
+ 'NULL-MD5');
+
+ $tested_ciphersuites = ssl_conn_ciphersuites($host, $port, $ciphersuites_to_test);
+ $result["supported_ciphersuites"] = array();
+ foreach ($tested_ciphersuites as $key => $value) {
+ if ($value == true) {
+ $result["supported_ciphersuites"][] = $key;
+ }
+ }
+
+ } else {
+ $result["used_ciphersuite"]["name"] = $context_meta['cipher_name'];
+ $result["used_ciphersuite"]["bits"] = $context_meta['cipher_bits'];
+ }
+ // tls_fallback_scsv
+ $fallback = tls_fallback_scsv($host, $port);
+ if ($fallback['protocol_count'] == 1) {
+ $result["tls_fallback_scsv"] = "Only 1 protocol enabled, fallback not possible, TLS_FALLBACK_SCSV not required.";
+ } else {
+ if ($fallback['tls_fallback_scsv_support'] == 1) {
+ $result["tls_fallback_scsv"] = "supported";
+ } else {
+ $result["tls_fallback_scsv"] = "unsupported";
+ }
+ }
+ //hsts
+ $headers = server_http_headers($host, $port);
+ if ($headers["strict-transport-security"]) {
+ if ( is_array($headers["strict-transport-security"])) {
+ $result["strict_sransport-security"] = substr($headers["strict-transport-security"][0], 0, 50);
+ } else {
+ $result["strict_transport_security"] = substr($headers["strict-transport-security"], 0, 50);
+ }
+ } else {
+ $result["strict_transport_security"] = 'not set';
+ }
+ //hpkp
+ if ( $headers["public-key-pins"] ) {
+ if ( is_array($headers["public-key-pins"])) {
+ $result["public_key_pins"] = substr($headers["public-key-pins"][0], 0, 255);
+ } else {
+ $result["public_key_pins"] = substr($headers["public-key-pins"], 0, 255);
+ }
+ } else {
+ $result["public_key_pins"] = 'not set';
+ }
+ if ( $headers["public-key-pins-report-only"] ) {
+ if ( is_array($headers["public-key-pins-report-only"])) {
+ $result["public_key_pins_report_only"] = substr($headers["public-key-pins-report-only"][0], 0, 255);
+ } else {
+ $result["public_key_pins_report_only"] = substr($headers["public-key-pins-report-only"], 0, 255);
+ }
+ }
+ // ocsp stapling
+ $stapling = ocsp_stapling($host,$port);
+ if($stapling["working"] == 1) {
+ $result["ocsp_stapling"] = $stapling;
+ } else {
+ $result["ocsp_stapling"] = "not set";
+ }
+
+ $result["openssl_version"] = shell_exec("openssl version");
+ $result["datetime_rfc2822"] = shell_exec("date --rfc-2822");
+ }
+ return $result;
}
+
+
+
+
?>
diff --git a/functions/crl.php b/functions/crl.php
index 3491a95..9c062c5 100644
--- a/functions/crl.php
+++ b/functions/crl.php
@@ -98,4 +98,83 @@ function crl_verify($raw_cert_data, $verbose=true) {
}
}
+
+function crl_verify_json($raw_cert_data) {
+ global $random_blurp;
+ $result = [];
+ $cert_data = openssl_x509_parse($raw_cert_data);
+ $cert_serial_nm = strtoupper(bcdechex($cert_data['serialNumber']));
+ $crl_uris = [];
+ $crl_uri = explode("\nFull Name:\n ", $cert_data['extensions']['crlDistributionPoints']);
+ foreach ($crl_uri as $key => $uri) {
+ if (isset($uri) ) {
+ $uri = explode("URI:", $uri);
+ $uri = $uri[1];
+ if (isset($uri) ) {
+ $crl_uris[] = preg_replace('/\s+/', '', $uri);
+ }
+ }
+ }
+ foreach ($crl_uris as $key => $uri) {
+ $crl_no = $key+1;
+ if (0 === strpos($uri, 'http')) {
+ $result[$crl_no]["crl_uri"] = $uri;
+ $fp = fopen ("/tmp/" . $random_blurp . "." . $key . ".crl", 'w+');
+ $ch = curl_init(($uri));
+ curl_setopt($ch, CURLOPT_TIMEOUT, 2);
+ curl_setopt($ch, CURLOPT_FILE, $fp);
+ curl_setopt($ch, CURLOPT_FAILONERROR, true);
+ curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
+ curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
+ if(curl_exec($ch) === false) {
+ $result[$crl_no]["error"] = 'Curl error: ' . htmlspecialchars(curl_error($ch));
+ return $result;
+ }
+ curl_close($ch);
+ if(stat("/tmp/" . $random_blurp . "." . escapeshellcmd($key) . ".crl")['size'] < 10 ) {
+ $result[$crl_no]["error"] = "crl could not be retreived";
+ }
+ $crl_text = shell_exec("openssl crl -noout -text -inform der -in /tmp/" . $random_blurp . "." . escapeshellcmd($key) . ".crl 2>&1");
+
+ $crl_last_update = shell_exec("openssl crl -noout -lastupdate -inform der -in /tmp/" . $random_blurp . "." . escapeshellcmd($key) . ".crl");
+ $crl_last_update = explode("=", $crl_last_update)[1];
+
+ $crl_next_update = shell_exec("openssl crl -noout -nextupdate -inform der -in /tmp/" . $random_blurp . "." . escapeshellcmd($key) . ".crl");
+ $crl_next_update = explode("=", $crl_next_update)[1];
+
+ unlink("/tmp/" . $random_blurp . "." . escapeshellcmd($key) . ".crl");
+
+ if ( strpos($crl_text, "unable to load CRL") === 0 ) {
+ $result[$crl_no]["status"] = "invalid";
+ }
+
+ $crl_info = explode("Revoked Certificates:", $crl_text)[0];
+ $crl_certificates = explode("Revoked Certificates:", $crl_text)[1];
+ $crl_certificates = explode("Serial Number:", $crl_certificates);
+ $revcert = array();
+ foreach ($crl_certificates as $key => $revoked_certificate) {
+ if (!empty($revoked_certificate)) {
+ $revcert[str_replace(" ", "", explode("\n", $revoked_certificate)[0])] = str_replace(" Revocation Date: ", "", explode("\n", $revoked_certificate)[1]);
+ }
+ }
+ if( array_key_exists($cert_serial_nm, $revcert) ) {
+ $result[$crl_no]["status"] = "revoked";
+ $result[$crl_no]["revoked_on"] = $revcert[$cert_serial_nm];
+ $result[$crl_no]["crl_last_update"] = $crl_last_update;
+ $result[$crl_no]["crl_next_update"] = $crl_next_update;
+ } else {
+ $result[$crl_no]["status"] = "ok";
+ $result[$crl_no]["crl_last_update"] = $crl_last_update;
+ $result[$crl_no]["crl_next_update"] = $crl_next_update;
+ }
+ }
+ }
+ return $result;
+}
+
+
+
+
?> \ No newline at end of file
diff --git a/functions/ocsp.php b/functions/ocsp.php
index 299a1fd..c9d43eb 100644
--- a/functions/ocsp.php
+++ b/functions/ocsp.php
@@ -15,92 +15,153 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
function ocsp_stapling($host, $port){
- $result = "";
- $output = shell_exec('echo | timeout 2 openssl s_client -connect "' . escapeshellcmd($host) . ':' . escapeshellcmd($port) . '" -tlsextdebug -status 2>&1 | sed -n "/OCSP response:/,/---/p"');
- if (strpos($output, "no response sent") !== false) {
- $result = array("working" => 0,
- "cert_status" => "No response sent");
- return;
- }
- if (strpos($output, "OCSP Response Data:") !== false) {
- $lines = array();
- $output = preg_replace("/[[:blank:]]+/"," ", $output);
- $stapling_status_lines = explode("\n", $output);
- $stapling_status_lines = array_map('trim', $stapling_status_lines);
- foreach($stapling_status_lines as $line) {
- if(endsWith($line, ":") == false) {
- list($k, $v) = explode(":", $line);
- $lines[trim($k)] = trim($v);
- }
- }
- $result = array("working" => 1,
- "Cert Status" => $lines["Cert Status"],
- "This Update" => $lines["This Update"],
- "Next Update" => $lines["Next Update"],
- "Responder ID" => $lines["Responder Id"],
- "Hash Algorithm" => $lines["Hash Algorithm"],
- "Signature Algorithm" => $lines["Signature Algorithm"],
- "Issuer Name Hash" => $lines["Issuer Name Hash"]);
+ $result = "";
+ $output = shell_exec('echo | timeout 2 openssl s_client -connect "' . escapeshellcmd($host) . ':' . escapeshellcmd($port) . '" -tlsextdebug -status 2>&1 | sed -n "/OCSP response:/,/---/p"');
+ if (strpos($output, "no response sent") !== false) {
+ $result = array("working" => 0,
+ "cert_status" => "No response sent");
+ return;
+ }
+ if (strpos($output, "OCSP Response Data:") !== false) {
+ $lines = array();
+ $output = preg_replace("/[[:blank:]]+/"," ", $output);
+ $stapling_status_lines = explode("\n", $output);
+ $stapling_status_lines = array_map('trim', $stapling_status_lines);
+ foreach($stapling_status_lines as $line) {
+ if(endsWith($line, ":") == false) {
+ list($k, $v) = explode(":", $line);
+ $lines[trim($k)] = trim($v);
+ }
}
- return $result;
+ $result = array("working" => 1,
+ "Cert Status" => $lines["Cert Status"],
+ "This Update" => $lines["This Update"],
+ "Next Update" => $lines["Next Update"],
+ "Responder ID" => $lines["Responder Id"],
+ "Hash Algorithm" => $lines["Hash Algorithm"],
+ "Signature Algorithm" => $lines["Signature Algorithm"],
+ "Issuer Name Hash" => $lines["Issuer Name Hash"]);
+ }
+ return $result;
}
function ocsp_verify($raw_cert_data, $raw_next_cert_data) {
- global $random_blurp;
- $cert_data = openssl_x509_parse($raw_cert_data);
- $tmp_dir = '/tmp/';
- $root_ca = getcwd() . '/cacert.pem';
-
- $pem_issuer = "";
- $pem_client = "";
- $ocsp_uri = explode("OCSP - URI:", $cert_data['extensions']['authorityInfoAccess'])[1];
- $ocsp_uri = explode("\n", $ocsp_uri)[0];
- $ocsp_uri = explode(" ", $ocsp_uri)[0];
- if (empty($ocsp_uri) ) {
- $result = array('unknown' => "Could not find OCSP URI", );
- return $result;
+ global $random_blurp;
+ $cert_data = openssl_x509_parse($raw_cert_data);
+ $tmp_dir = '/tmp/';
+ $root_ca = getcwd() . '/cacert.pem';
+
+ $pem_issuer = "";
+ $pem_client = "";
+ $ocsp_uri = explode("OCSP - URI:", $cert_data['extensions']['authorityInfoAccess'])[1];
+ $ocsp_uri = explode("\n", $ocsp_uri)[0];
+ $ocsp_uri = explode(" ", $ocsp_uri)[0];
+ if (empty($ocsp_uri) ) {
+ $result = array('unknown' => "Could not find OCSP URI", );
+ return $result;
+ }
+ openssl_x509_export($raw_cert_data, $pem_client);
+ openssl_x509_export($raw_next_cert_data, $pem_issuer);
+ openssl_x509_export_to_file($raw_next_cert_data, $tmp_dir.$random_blurp.'.cert_issuer.pem');
+ openssl_x509_export_to_file($raw_cert_data, $tmp_dir.$random_blurp.'.cert_client.pem');
+
+ // Some OCSP's want HTTP/1.1 but OpenSSL does not do that. Add Host header as workaround.
+ $ocsp_host = parse_url($ocsp_uri, PHP_URL_HOST);
+
+ //echo '<pre>' . htmlspecialchars('openssl ocsp -no_nonce -CAfile '.$root_ca.' -issuer '.$tmp_dir.$random_blurp.'.cert_issuer.pem -cert '.$tmp_dir.$random_blurp.'.cert_client.pem -url "'. escapeshellcmd($ocsp_uri) . '" -header "HOST" "'. escapeshellcmd($ocsp_host) . '" 2>&1') . '</pre>';
+
+ $output = shell_exec('openssl ocsp -no_nonce -CAfile '.$root_ca.' -issuer '.$tmp_dir.$random_blurp.'.cert_issuer.pem -cert '.$tmp_dir.$random_blurp.'.cert_client.pem -url "'. escapeshellcmd($ocsp_uri) . '" -header "HOST" "'. escapeshellcmd($ocsp_host) . '" 2>&1');
+ $filter_output = shell_exec('openssl ocsp -no_nonce -CAfile '.$root_ca.' -issuer '.$tmp_dir.$random_blurp.'.cert_issuer.pem -cert '.$tmp_dir.$random_blurp.'.cert_client.pem -url "'. escapeshellcmd($ocsp_uri) . '" -header "HOST" "'. escapeshellcmd($ocsp_host) . '" 2>&1 | grep -v -e "to get local issuer certificate" -e "signer certificate not found" -e "Response Verify" -e "'. $tmp_dir.$random_blurp.'.cert_client.pem"');
+
+
+
+ $lines = array();
+ $output = preg_replace("/[[:blank:]]+/"," ", $output);
+ $ocsp_status_lines = explode("\n", $output);
+ $ocsp_status_lines = array_map('trim', $ocsp_status_lines);
+ foreach($ocsp_status_lines as $line) {
+ if(endsWith($line, ":") == false) {
+ list($k, $v) = explode(":", $line, 2);
+ $lines[trim($k)] = trim($v);
}
- openssl_x509_export($raw_cert_data, $pem_client);
- openssl_x509_export($raw_next_cert_data, $pem_issuer);
- openssl_x509_export_to_file($raw_next_cert_data, $tmp_dir.$random_blurp.'.cert_issuer.pem');
- openssl_x509_export_to_file($raw_cert_data, $tmp_dir.$random_blurp.'.cert_client.pem');
+ }
- // Some OCSP's want HTTP/1.1 but OpenSSL does not do that. Add Host header as workaround.
- $ocsp_host = parse_url($ocsp_uri, PHP_URL_HOST);
+ $result = array("This Update" => $lines["This Update"],
+ "Next Update" => $lines["Next Update"],
+ "Reason" => $lines["Reason"],
+ "Revocation Time" => $lines["Revocation Time"],
+ "ocsp_verify_status" => $lines[$tmp_dir . $random_blurp . ".cert_client.pem"]);
+ if ($result["ocsp_verify_status"] == "good") {
+ $result["good"] = $filter_output;
+ } else if ($result["ocsp_verify_status"] == "revoked") {
+ $result["revoked"] = $filter_output;
+ } else {
+ $result["unknown"] = $filter_output;
+ }
+ unlink($tmp_dir.$random_blurp.'.cert_client.pem');
+ unlink($tmp_dir.$random_blurp.'.cert_issuer.pem');
+ return $result;
+}
- //echo '<pre>' . htmlspecialchars('openssl ocsp -no_nonce -CAfile '.$root_ca.' -issuer '.$tmp_dir.$random_blurp.'.cert_issuer.pem -cert '.$tmp_dir.$random_blurp.'.cert_client.pem -url "'. escapeshellcmd($ocsp_uri) . '" -header "HOST" "'. escapeshellcmd($ocsp_host) . '" 2>&1') . '</pre>';
- $output = shell_exec('openssl ocsp -no_nonce -CAfile '.$root_ca.' -issuer '.$tmp_dir.$random_blurp.'.cert_issuer.pem -cert '.$tmp_dir.$random_blurp.'.cert_client.pem -url "'. escapeshellcmd($ocsp_uri) . '" -header "HOST" "'. escapeshellcmd($ocsp_host) . '" 2>&1');
- $filter_output = shell_exec('openssl ocsp -no_nonce -CAfile '.$root_ca.' -issuer '.$tmp_dir.$random_blurp.'.cert_issuer.pem -cert '.$tmp_dir.$random_blurp.'.cert_client.pem -url "'. escapeshellcmd($ocsp_uri) . '" -header "HOST" "'. escapeshellcmd($ocsp_host) . '" 2>&1 | grep -v -e "to get local issuer certificate" -e "signer certificate not found" -e "Response Verify" -e "'. $tmp_dir.$random_blurp.'.cert_client.pem"');
+function ocsp_verify_json($raw_cert_data, $raw_next_cert_data, $ocsp_uri) {
+ global $random_blurp;
+ $result = array();
+ $tmp_dir = '/tmp/';
+ $root_ca = getcwd() . '/cacert.pem';
+ $pem_issuer = "";
+ $pem_client = "";
+ openssl_x509_export($raw_cert_data, $pem_client);
+ openssl_x509_export($raw_next_cert_data, $pem_issuer);
+ openssl_x509_export_to_file($raw_next_cert_data, $tmp_dir.$random_blurp.'.cert_issuer.pem');
+ openssl_x509_export_to_file($raw_cert_data, $tmp_dir.$random_blurp.'.cert_client.pem');
+ // Some OCSP's want HTTP/1.1 but OpenSSL does not do that. Add Host header as workaround.
+ $ocsp_host = parse_url($ocsp_uri, PHP_URL_HOST);
+ $output = shell_exec('openssl ocsp -no_nonce -CAfile '.$root_ca.' -issuer '.$tmp_dir.$random_blurp.'.cert_issuer.pem -cert '.$tmp_dir.$random_blurp.'.cert_client.pem -url "'. escapeshellcmd($ocsp_uri) . '" -header "HOST" "'. escapeshellcmd($ocsp_host) . '" 2>&1');
+
+ $filter_output = shell_exec('openssl ocsp -no_nonce -CAfile '.$root_ca.' -issuer '.$tmp_dir.$random_blurp.'.cert_issuer.pem -cert '.$tmp_dir.$random_blurp.'.cert_client.pem -url "'. escapeshellcmd($ocsp_uri) . '" -header "HOST" "'. escapeshellcmd($ocsp_host) . '" 2>&1 | grep -v -e "to get local issuer certificate" -e "signer certificate not found" -e "Response Verify" -e "'. $tmp_dir.$random_blurp.'.cert_client.pem"');
- $lines = array();
- $output = preg_replace("/[[:blank:]]+/"," ", $output);
- $ocsp_status_lines = explode("\n", $output);
- $ocsp_status_lines = array_map('trim', $ocsp_status_lines);
- foreach($ocsp_status_lines as $line) {
- if(endsWith($line, ":") == false) {
- list($k, $v) = explode(":", $line, 2);
- $lines[trim($k)] = trim($v);
- }
- }
-
- $result = array("This Update" => $lines["This Update"],
- "Next Update" => $lines["Next Update"],
- "Reason" => $lines["Reason"],
- "Revocation Time" => $lines["Revocation Time"],
- "ocsp_verify_status" => $lines[$tmp_dir . $random_blurp . ".cert_client.pem"]);
- if ($result["ocsp_verify_status"] == "good") {
- $result["good"] = $filter_output;
- } else if ($result["ocsp_verify_status"] == "revoked") {
- $result["revoked"] = $filter_output;
- } else {
- $result["unknown"] = $filter_output;
+ $output = preg_replace("/[[:blank:]]+/"," ", $output);
+ $ocsp_status_lines = explode("\n", $output);
+ $ocsp_status_lines = array_map('trim', $ocsp_status_lines);
+ foreach($ocsp_status_lines as $line) {
+ if(endsWith($line, ":") == false) {
+ list($k, $v) = explode(":", $line, 2);
+ if (trim($k)) {
+ $lines[trim($k)] = trim($v);
+ }
}
- unlink($tmp_dir.$random_blurp.'.cert_client.pem');
- unlink($tmp_dir.$random_blurp.'.cert_issuer.pem');
- return $result;
+ }
+
+ if ($lines[$tmp_dir . $random_blurp . ".cert_client.pem"] == "good") {
+ $result["status"] = "good";
+ } else if ($lines[$tmp_dir . $random_blurp . ".cert_client.pem"] == "revoked") {
+ $result["status"] = "revoked";
+ } else {
+ $result["error"] = $filter_output;
+ $result["status"] = "unknown";
+ }
+
+ if (isset($lines["This Update"])) {
+ $result["this_update"] = $lines["This Update"];
+ }
+ if (isset($lines["Next Update"])) {
+ $result["next_update"] = $lines["Next Update"];
+ }
+ if (isset($lines["Reason"])) {
+ $result["reason"] = $lines["Reason"];
+ }
+ if (isset($lines["Revocation Time"])) {
+ $result["revocation_time"] = $lines["Revocation Time"];
+ }
+ $result["ocsp_uri"] = $ocsp_uri;
+
+ unlink($tmp_dir.$random_blurp.'.cert_client.pem');
+ unlink($tmp_dir.$random_blurp.'.cert_issuer.pem');
+
+ return $result;
}
?> \ No newline at end of file
diff --git a/functions/parse_certificate.php b/functions/parse_certificate.php
index 069b047..1c7c959 100644
--- a/functions/parse_certificate.php
+++ b/functions/parse_certificate.php
@@ -21,645 +21,807 @@ function get_cert_cn($raw_cert_data){
}
}
- function cert_parse($raw_cert_data, $raw_next_cert_data=null, $csr=false, $host=null, $port=null, $is_issuer=false) {
- global $random_blurp;
- global $ev_oids;
+function cert_parse($raw_cert_data, $raw_next_cert_data=null, $csr=false, $host=null, $port=null, $is_issuer=false) {
+ global $random_blurp;
+ global $ev_oids;
- if ($csr == true && strpos($raw_cert_data, "BEGIN CERTIFICATE REQUEST") !== false) {
- ?>
- <table class="table table-striped table-bordered">
- <tr>
- <td colspan="2"><strong>Certificate Data</strong></td>
- </tr>
- <?php
- $cert_data = openssl_csr_get_public_key($raw_cert_data);
-
- $cert_details = openssl_pkey_get_details($cert_data);
- $cert_key = $cert_details['key'];
- $cert_subject = openssl_csr_get_subject($raw_cert_data);
-
- foreach ($cert_subject as $key => $value) {
- echo "<tr><td>";
- switch ($key) {
- case 'C':
- echo "Country";
- break;
- case 'ST':
- echo "State";
- break;
- case 'L':
- echo "City";
- break;
- case 'O':
- echo "Organization";
- break;
- case 'OU':
- echo "Organizational Unit";
- break;
- case 'CN':
- echo "Common Name";
- break;
- case 'mail':
- echo "Email Address";
- break;
- default:
- echo htmlspecialchars($key);
- break;
- }
+ if ($csr == true && strpos($raw_cert_data, "BEGIN CERTIFICATE REQUEST") !== false) {
+ ?>
+ <table class="table table-striped table-bordered">
+ <tr>
+ <td colspan="2"><strong>Certificate Data</strong></td>
+ </tr>
+ <?php
+ $cert_data = openssl_csr_get_public_key($raw_cert_data);
- echo "</td><td>";
- switch ($key) {
- case 'C':
- echo htmlspecialchars($value);
- echo ' <img src="'.htmlspecialchars($current_folder) . 'img/blank.gif" class="flag flag-';
- echo strtolower(htmlspecialchars($value));
- echo '" alt="" />';
- break;
- case 'DC':
- foreach ($value as $key => $value) {
- echo htmlspecialchars($value) . ".";
- }
- break;
- default:
- if (is_array($value)) {
- foreach ($value as $key => $value) {
- echo htmlspecialchars($value) . " ";
- }
- } else {
- echo htmlspecialchars($value);
- }
- break;
- }
+ $cert_details = openssl_pkey_get_details($cert_data);
+ $cert_key = $cert_details['key'];
+ $cert_subject = openssl_csr_get_subject($raw_cert_data);
- echo "</td></tr>\n";
+ foreach ($cert_subject as $key => $value) {
+ echo "<tr><td>";
+ switch ($key) {
+ case 'C':
+ echo "Country";
+ break;
+ case 'ST':
+ echo "State";
+ break;
+ case 'L':
+ echo "City";
+ break;
+ case 'O':
+ echo "Organization";
+ break;
+ case 'OU':
+ echo "Organizational Unit";
+ break;
+ case 'CN':
+ echo "Common Name";
+ break;
+ case 'mail':
+ echo "Email Address";
+ break;
+ default:
+ echo htmlspecialchars($key);
+ break;
+ }
+
+ echo "</td><td>";
+ switch ($key) {
+ case 'C':
+ echo htmlspecialchars($value);
+ echo ' <img src="'.htmlspecialchars($current_folder) . 'img/blank.gif" class="flag flag-';
+ echo strtolower(htmlspecialchars($value));
+ echo '" alt="" />';
+ break;
+ case 'DC':
+ foreach ($value as $key => $value) {
+ echo htmlspecialchars($value) . ".";
+ }
+ break;
+ default:
+ if (is_array($value)) {
+ foreach ($value as $key => $value) {
+ echo htmlspecialchars($value) . " ";
}
- echo "</table>";
- return;
} else {
- $cert_data = openssl_x509_parse($raw_cert_data);
- }
- if (empty($cert_data)) {
- echo "Data not valid.";
- continue;
+ echo htmlspecialchars($value);
}
- ?>
- <table class="table table-striped table-bordered">
- <tr>
- <td colspan="2"><strong>Certificate Data</strong></td>
- </tr>
- <?php
- $next_cert_data = openssl_x509_parse($raw_next_cert_data);
- $today = date("Y-m-d");
- echo "<tr><td colspan='2'>\n";
- echo "<table class='table'>\n";
- echo "<thead><tr>\n";
- echo "<th>Hostname</th>\n";
- echo "<th>Not Expired</th>\n";
- echo "<th>Issuer</th>\n";
- echo "<th>CRL</th>\n";
- echo "<th>OCSP</th>\n";
- echo "<th>Signing Type</th>\n";
- echo "</tr>\n</thead>\n<tbody>\n<tr>";
- // hostname
- if ($is_issuer == false) {
- if ($csr == false) {
- if ($cert_data['subject']['CN']) {
- if ( verify_certificate_hostname($raw_cert_data, $host, $port) ) {
- echo '<td><h1><span class="text-success glyphicon glyphicon-ok"></span>&nbsp;</h1></td>';
- } else {
- echo '<td><h1><span class="text-danger glyphicon glyphicon-remove"></span>&nbsp;</h1></td>';
- }
- }
- } else {
- echo "<td></td>";
- }
- } else {
- echo "<td></td>";
- }
- // expired
- if ( $today > date(DATE_RFC2822,$cert_data['validFrom_time_t']) || strtotime($today) < strtotime(date(DATE_RFC2822,$cert_data['validTo_time_t'])) ) {
+ break;
+ }
+
+ echo "</td></tr>\n";
+ }
+ echo "</table>";
+ return;
+ } else {
+ $cert_data = openssl_x509_parse($raw_cert_data);
+ }
+ if (empty($cert_data)) {
+ echo "Data not valid.";
+ continue;
+ }
+ ?>
+ <table class="table table-striped table-bordered">
+ <tr>
+ <td colspan="2"><strong>Certificate Data</strong></td>
+ </tr>
+ <?php
+ $next_cert_data = openssl_x509_parse($raw_next_cert_data);
+ $today = date("Y-m-d");
+ echo "<tr><td colspan='2'>\n";
+ echo "<table class='table'>\n";
+ echo "<thead><tr>\n";
+ echo "<th>Hostname</th>\n";
+ echo "<th>Not Expired</th>\n";
+ echo "<th>Issuer</th>\n";
+ echo "<th>CRL</th>\n";
+ echo "<th>OCSP</th>\n";
+ echo "<th>Signing Type</th>\n";
+ echo "</tr>\n</thead>\n<tbody>\n<tr>";
+ // hostname
+ if ($is_issuer == false) {
+ if ($csr == false) {
+ if ($cert_data['subject']['CN']) {
+ if ( verify_certificate_hostname($raw_cert_data, $host) ) {
echo '<td><h1><span class="text-success glyphicon glyphicon-ok"></span>&nbsp;</h1></td>';
} else {
echo '<td><h1><span class="text-danger glyphicon glyphicon-remove"></span>&nbsp;</h1></td>';
}
+ }
+ } else {
+ echo "<td></td>";
+ }
+ } else {
+ echo "<td></td>";
+ }
+// expired
+ if ( $today > date(DATE_RFC2822,$cert_data['validFrom_time_t']) || strtotime($today) < strtotime(date(DATE_RFC2822,$cert_data['validTo_time_t'])) ) {
+ echo '<td><h1><span class="text-success glyphicon glyphicon-ok"></span>&nbsp;</h1></td>';
+ } else {
+ echo '<td><h1><span class="text-danger glyphicon glyphicon-remove"></span>&nbsp;</h1></td>';
+ }
// issuer
- if ($raw_next_cert_data) {
- if (verify_cert_issuer_by_subject_hash($raw_cert_data, $raw_next_cert_data) ) {
- echo '<td><h1><span class="text-success glyphicon glyphicon-ok"></span>&nbsp;</h1></td>';
- } else {
- echo '<td><h1><span class="text-danger glyphicon glyphicon-remove"></span>&nbsp;</h1></td>';
+ if ($raw_next_cert_data) {
+ if (verify_cert_issuer_by_subject_hash($raw_cert_data, $raw_next_cert_data) ) {
+ echo '<td><h1><span class="text-success glyphicon glyphicon-ok"></span>&nbsp;</h1></td>';
+ } else {
+ echo '<td><h1><span class="text-danger glyphicon glyphicon-remove"></span>&nbsp;</h1></td>';
+ }
+ } else {
+ echo '<td> </td>';
+ }
+// crl
+ if ( !empty($cert_data['extensions']['crlDistributionPoints']) ) {
+ echo "<td><h1>" . crl_verify($raw_cert_data, false) . " &nbsp; </h1></td>";
+ } else {
+ echo '<td> </td>';
+ }
+// ocsp
+ if ( !empty($cert_data['extensions']['authorityInfoAccess']) && !empty($next_cert_data) ) {
+ echo "<td>";
+ $ocsp_uri = explode("OCSP - URI:", $cert_data['extensions']['authorityInfoAccess'])[1];
+ $ocsp_uri = explode("\n", $ocsp_uri)[0];
+ $ocsp_uri = explode(" ", $ocsp_uri)[0];
+ if (!empty($ocsp_uri)) {
+ $ocsp_result = ocsp_verify($raw_cert_data, $raw_next_cert_data);
+ if ($ocsp_result["ocsp_verify_status"] == "good") {
+ echo '<h1><span class="text-success glyphicon glyphicon-ok"></span>&nbsp;</h1>';
+ } else if ($ocsp_result["ocsp_verify_status"] == "revoked") {
+ echo '<h1><span class="text-danger glyphicon glyphicon-remove"></span>&nbsp;</h1>';
+ } else {
+ echo '<h1><span class="text-danger glyphicon glyphicon-question-sign"></span>&nbsp;</h1>';
+ }
+ } else {
+ echo "<td></td>";
+ }
+ echo "</td>";
+ } else {
+ echo "<td> </td>";
+ }
+ // self signed/ca/ca root
+ if (strpos($cert_data['extensions']['basicConstraints'], "CA:TRUE") !== false && $cert_data['issuer']['CN'] == $cert_data['subject']['CN'] ) {
+ echo '<td><span class="text-success">CA Root Certificate</span></td>';
+ } else if (strpos($cert_data['extensions']['basicConstraints'], "CA:TRUE") !== false) {
+ echo '<td><span class="text-success">CA Certificate</span></td>';
+ } else if ($cert_data['issuer']['CN'] == $cert_data['subject']['CN']) {
+ echo '<td><span class="text-danger">Self Signed</span></td>';
+ } else {
+ echo "<td>Signed by CA</td>";
+ }
+ echo "</tr>";
+ echo "</tbody></table>";
+ echo "</td></tr>";
+
+
+ if (!empty($cert_data['subject']) ) {
+ foreach ($cert_data['subject'] as $key => $value) {
+ echo "<tr><td>";
+ switch ($key) {
+ case 'C':
+ echo "Country";
+ break;
+ case 'ST':
+ echo "State";
+ break;
+ case 'L':
+ echo "City";
+ break;
+ case 'O':
+ echo "Organization";
+ break;
+ case 'OU':
+ echo "Organizational Unit";
+ break;
+ case 'CN':
+ echo "Common Name";
+ break;
+ case 'mail':
+ echo "Email Address";
+ break;
+ case 'businessCategory':
+ echo "Business Type";
+ break;
+ default:
+ echo htmlspecialchars($key);
+ break;
+ }
+ echo "</td><td>";
+ switch ($key) {
+ case 'C':
+ echo htmlspecialchars($value);
+ echo ' <img src="'.htmlspecialchars($current_folder) . 'img/blank.gif" class="flag flag-';
+ echo strtolower(htmlspecialchars($value));
+ echo '" alt="" />';
+ break;
+ case 'DC':
+ foreach ($value as $key => $value) {
+ echo htmlspecialchars($value) . ".";
+ }
+ break;
+ default:
+ if (is_array($value)) {
+ foreach ($value as $key => $value) {
+ echo htmlspecialchars($value) . " ";
}
} else {
- echo '<td> </td>';
+ echo htmlspecialchars($value);
}
-// crl
- if ( !empty($cert_data['extensions']['crlDistributionPoints']) ) {
- echo "<td><h1>" . crl_verify($raw_cert_data, false) . " &nbsp; </h1></td>";
- } else {
- echo '<td> </td>';
+ break;
+ }
+ echo "</td></tr>\n";
+ }
+
+
+ }
+ if (!empty($cert_data['extensions']['subjectAltName'])) {
+ ?>
+ <tr>
+ <td>Subject Alternative Names</td>
+ <td>
+ <?php
+ foreach ( explode("DNS:", $cert_data['extensions']['subjectAltName']) as $altName ) {
+ if ( !empty(str_replace(',', " ", "$altName"))) {
+ echo htmlspecialchars(str_replace(',', " ", "$altName"));
+ echo "<br>";
+ }
+ }
+ ?>
+ </td>
+ </tr>
+ <?php
+ }
+ ?>
+ <tr>
+ <td>Type</td>
+ <td>
+ <?php
+ if ( array_search(explode("Policy: ", explode("\n", $cert_data['extensions']['certificatePolicies'])[0])[1], $ev_oids) ) {
+ echo '<span class="text-success">Extended Validation</span>';
+ } else if ( isset($cert_data['subject']['O'] ) ) {
+ echo "Organisation Validation";
+ } else if ( isset($cert_data['subject']['CN'] ) ) {
+ echo "Domain Validation";
+ }
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td>Full Subject</td>
+ <td><?php echo htmlspecialchars($cert_data['name']); ?></td>
+ </tr>
+ <tr>
+ <td colspan="2"><strong>Issuer</strong></td>
+ </tr>
+ <?php
+ if (!empty($cert_data['issuer']) ) {
+ foreach ($cert_data['issuer'] as $key => $value) {
+ echo "<tr><td>";
+ switch ($key) {
+ case 'C':
+ echo "Country";
+ break;
+ case 'ST':
+ echo "State";
+ break;
+ case 'L':
+ echo "City";
+ break;
+ case 'O':
+ echo "Organization";
+ break;
+ case 'OU':
+ echo "Organizational Unit";
+ break;
+ case 'CN':
+ echo "Common Name";
+ break;
+ case 'mail':
+ echo "Email Address";
+ break;
+ case 'emailAddress':
+ echo "Email Address";
+ break;
+ default:
+ echo htmlspecialchars($key);
+ break;
+ }
+ echo "</td><td>";
+ switch ($key) {
+ case 'C':
+ echo htmlspecialchars($value);
+ echo ' <img src="'.htmlspecialchars($current_folder) . 'img/blank.gif" class="flag flag-';
+ echo strtolower(htmlspecialchars($value));
+ echo '" alt="" />';
+ break;
+ case 'DC':
+ foreach ($value as $key => $value) {
+ echo htmlspecialchars($value) . ".";
}
-// ocsp
- if ( !empty($cert_data['extensions']['authorityInfoAccess']) && !empty($next_cert_data) ) {
- echo "<td>";
- $ocsp_uri = explode("OCSP - URI:", $cert_data['extensions']['authorityInfoAccess'])[1];
- $ocsp_uri = explode("\n", $ocsp_uri)[0];
- $ocsp_uri = explode(" ", $ocsp_uri)[0];
- if (!empty($ocsp_uri)) {
- $ocsp_result = ocsp_verify($raw_cert_data, $raw_next_cert_data);
- if ($ocsp_result["ocsp_verify_status"] == "good") {
- echo '<h1><span class="text-success glyphicon glyphicon-ok"></span>&nbsp;</h1>';
- } else if ($ocsp_result["ocsp_verify_status"] == "revoked") {
- echo '<h1><span class="text-danger glyphicon glyphicon-remove"></span>&nbsp;</h1>';
- } else {
- echo '<h1><span class="text-danger glyphicon glyphicon-question-sign"></span>&nbsp;</h1>';
- }
- } else {
- echo "<td></td>";
+ break;
+ default:
+ if (is_array($value)) {
+ foreach ($value as $key => $value) {
+ echo htmlspecialchars($value) . " ";
}
- echo "</td>";
} else {
- echo "<td> </td>";
+ echo htmlspecialchars($value);
}
- // self signed/ca/ca root
- if (strpos($cert_data['extensions']['basicConstraints'], "CA:TRUE") !== false && $cert_data['issuer']['CN'] == $cert_data['subject']['CN'] ) {
- echo '<td><span class="text-success">CA Root Certificate</span></td>';
- } else if (strpos($cert_data['extensions']['basicConstraints'], "CA:TRUE") !== false) {
- echo '<td><span class="text-success">CA Certificate</span></td>';
- } else if ($cert_data['issuer']['CN'] == $cert_data['subject']['CN']) {
- echo '<td><span class="text-danger">Self Signed</span></td>';
+ break;
+ }
+ echo "</td></tr>\n";
+ }
+ }
+ ?>
+ <tr>
+ <td colspan="2"><strong>Validity</strong></td>
+ </tr>
+ <?php
+ if ( !empty($cert_data['validFrom_time_t']) ) {
+ ?>
+ <tr>
+ <td>Valid From</td>
+ <td>
+ <?php
+ if ( $today < date(DATE_RFC2822,$cert_data['validFrom_time_t']) ) {
+ echo '<span class="text-success glyphicon glyphicon-ok-sign"></span>';
+ echo '<span class="text-success"> - ';
} else {
- echo "<td>Signed by CA</td>";
+ echo '<span class="text-danger glyphicon glyphicon-exclamation-sign"></span>';
+ echo '<span class="text-danger"> - ';
+
}
- echo "</tr>";
- echo "</tbody></table>";
- echo "</td></tr>";
-
-
- if (!empty($cert_data['subject']) ) {
- foreach ($cert_data['subject'] as $key => $value) {
- echo "<tr><td>";
- switch ($key) {
- case 'C':
- echo "Country";
- break;
- case 'ST':
- echo "State";
- break;
- case 'L':
- echo "City";
- break;
- case 'O':
- echo "Organization";
- break;
- case 'OU':
- echo "Organizational Unit";
- break;
- case 'CN':
- echo "Common Name";
- break;
- case 'mail':
- echo "Email Address";
- break;
- case 'businessCategory':
- echo "Business Type";
- break;
- default:
- echo htmlspecialchars($key);
- break;
- }
- echo "</td><td>";
- switch ($key) {
- case 'C':
- echo htmlspecialchars($value);
- echo ' <img src="'.htmlspecialchars($current_folder) . 'img/blank.gif" class="flag flag-';
- echo strtolower(htmlspecialchars($value));
- echo '" alt="" />';
- break;
- case 'DC':
- foreach ($value as $key => $value) {
- echo htmlspecialchars($value) . ".";
- }
- break;
- default:
- if (is_array($value)) {
- foreach ($value as $key => $value) {
- echo htmlspecialchars($value) . " ";
- }
- } else {
- echo htmlspecialchars($value);
- }
- break;
- }
- echo "</td></tr>\n";
- }
+ echo htmlspecialchars(date(DATE_RFC2822,$cert_data['validFrom_time_t']));
+ echo "</span>";
+ ?>
+ </td>
+ </tr>
+ <?php
+ };
+ if ( !empty($cert_data['validTo_time_t']) ) {
+ ?>
+ <tr>
+ <td>Valid Until</td>
+ <td>
+ <?php
+ if ( strtotime($today) < strtotime(date(DATE_RFC2822,$cert_data['validTo_time_t'])) ) {
+ echo '<span class="text-success glyphicon glyphicon-ok-sign"></span>';
+ echo '<span class="text-success"> - ';
+ } else {
+ echo '<span class="text-danger glyphicon glyphicon-exclamation-sign"></span>';
+ echo '<span class="text-danger"> - ';
+ }
+ echo htmlspecialchars(date(DATE_RFC2822,$cert_data['validTo_time_t']));
+ echo "</span>";
+ ?>
+ </td>
+ </tr>
+ <?php
+ };
+ if ( !empty($cert_data['extensions']['crlDistributionPoints']) ) {
+ ?>
+ <tr>
+ <td>CRL</td>
+ <td>
+ <?php
+ echo crl_verify($raw_cert_data);
+ ?>
+ </td>
+ </tr>
+ <?php
+ } else {
+ echo "<tr><td>CRL</td><td>No CRL URI found in certificate</td></tr>";
+ }
+ if ( !empty($cert_data['extensions']['authorityInfoAccess']) && !empty($next_cert_data) ) {
+ ?>
+ <tr>
+ <td>OCSP</td>
+ <td>
+ <?php
+ $ocsp_uri = explode("OCSP - URI:", $cert_data['extensions']['authorityInfoAccess'])[1];
+ $ocsp_uri = explode("\n", $ocsp_uri)[0];
+ $ocsp_uri = explode(" ", $ocsp_uri)[0];
+ if ( isset($raw_next_cert_data) && !empty($ocsp_uri) ) {
+ if ($ocsp_result["ocsp_verify_status"] == "good") {
+ echo '<span class="text-success glyphicon glyphicon-ok-sign"></span> ';
+ echo '<span class="text-success"> - OK: ';
+ echo htmlspecialchars($ocsp_uri);
+ echo "</span><br><pre>This update: " . htmlspecialchars($ocsp_result["This Update"]) . " - ";
+ echo "<br>Next update: " . htmlspecialchars($ocsp_result["Next Update"]) . "</pre>";
+ } else if ( $ocsp_result["ocsp_verify_status"] == "revoked") {
+ echo '<span class="text-danger glyphicon glyphicon-remove-sign"></span>';
+ echo '<span class="text-danger"> - REVOKED: ';
+ echo htmlspecialchars($ocsp_uri);
+ echo "</span><br><pre>This update: " . htmlspecialchars($ocsp_result["This Update"]);
+ echo "<br>Next update: " . htmlspecialchars($ocsp_result["Next Update"]);
+ echo "<br>Revocation Time: " . htmlspecialchars($ocsp_result["Revocation Time"]);
+ echo "<br>Revocation Reason: " . htmlspecialchars($ocsp_result["Reason"]). "</pre>";
+ } else {
+ echo '<span class="text-danger glyphicon glyphicon-question-sign"></span>';
+ echo '<span class="text-danger"> - UNKNOWN: ';
+
+ echo " - " . htmlspecialchars($ocsp_uri) . "</span><br>";
+ echo "<pre>" . htmlspecialchars($ocsp_result["unknown"]) . "</pre>";
+ }
+ } else {
+ echo "No OCSP URI found in certificate";
+ }
+ ?>
+ </td>
+ </tr>
+ <?php
+ } else {
+ echo "<tr><td>OCSP</td><td>No OCSP URI found in certificate</td></tr>";
+ }
+ if ($is_issuer == false && $csr == false) {
+ if ($cert_data['subject']['CN']) {
+ echo '<tr><td>Hostname</td>';
+ if ( verify_certificate_hostname($raw_cert_data, $host, $port) ) {
+ echo "<td><span class='text-success glyphicon glyphicon-ok'></span>\n<span class='text-success'> - ";
+ echo htmlspecialchars($host);
+ echo " found in CN or SAN.</span></td></tr>";
+ } else {
+
+ echo '<td><span class="text-danger glyphicon glyphicon-remove"></span><span class="text-danger"> - ';
+ echo htmlspecialchars($host);
+ echo ' NOT found in CN or SAN.</span></td></tr>';
+ }
+ }
+ } else {
+ if ($csr == false) {
+ echo "<tr><td>Hostname</td><td>Not applicable, this seems to be a CA signing certificate.</td></tr>";
+ } else {
+ echo "<tr><td>Hostname</td><td>Not applicable, this seems to be a CSR.</td></tr>";
+ }
+ }
+ ?>
+ <tr>
+ <td colspan="2"><strong>Details</strong></td>
+ </tr>
+ <?php
+ if ( !empty($cert_data['purposes']) ) {
+ ?>
+ <tr>
+ <td>Purposes</td>
+ <td>
+ <?php
+ $purposes_len = count($cert_data['purposes']);
+ foreach ($cert_data['purposes'] as $key => $purpose) {
+ echo htmlspecialchars($purpose[2]);
+ if ( $key != $purposes_len - 1) {
+ echo ", ";
+ }
}
- if (!empty($cert_data['extensions']['subjectAltName'])) {
?>
- <tr>
- <td>Subject Alternative Names</td>
- <td>
- <?php
- foreach ( explode("DNS:", $cert_data['extensions']['subjectAltName']) as $altName ) {
- if ( !empty(str_replace(',', " ", "$altName"))) {
- echo htmlspecialchars(str_replace(',', " ", "$altName"));
- echo "<br>";
- }
- }
- ?>
- </td>
- </tr>
+ </td>
+ </tr>
+ <?php
+ };
+ if ( !empty($cert_data['serialNumber']) ) {
+ ?>
+ <tr>
+ <td>Serial</td>
+ <td><code>
<?php
+ $sn = str_split(strtoupper(bcdechex($cert_data['serialNumber'])), 2);
+ $sn_len = count($sn);
+ foreach ($sn as $key => $s) {
+ echo htmlspecialchars($s);
+ if ( $key != $sn_len - 1) {
+ echo ":";
+ }
}
?>
- <tr>
- <td>Type</td>
- <td>
- <?php
- if ( array_search(explode("Policy: ", explode("\n", $cert_data['extensions']['certificatePolicies'])[0])[1], $ev_oids) ) {
- echo '<span class="text-success">Extended Validation</span>';
- } else if ( isset($cert_data['subject']['O'] ) ) {
- echo "Organisation Validation";
- } else if ( isset($cert_data['subject']['CN'] ) ) {
- echo "Domain Validation";
- }
- ?>
+ </code></td>
+ </tr>
+ <?php
+ }
+ ?>
+ <tr>
+ <td>Key Size / Type</td>
+ <td>
+ <?php
+
+
+ $key_details = openssl_pkey_get_details(openssl_pkey_get_public($raw_cert_data));
+ $export_pem = "";
+ openssl_x509_export($raw_cert_data, $export_pem);
+
+ if ( $key_details['rsa'] ) {
+ echo htmlspecialchars($key_details['bits']);
+ echo " bits RSA";
+ } else if ( $key_details['dsa'] ) {
+ echo htmlspecialchars($key_details['bits']);
+ echo " bits DSA";
+ } else if ( $key_details['dh'] ) {
+ echo htmlspecialchars($key_details['bits']);
+ echo " bits DH";
+ } else {
+ echo htmlspecialchars(var_dump($key_details['bits']));
+ echo " bits";
+ }
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td>Signature Algorithm</td>
+ <td>
+ <?php
+ $signature_algorithm = cert_signature_algorithm($raw_cert_data);
+ echo htmlspecialchars($signature_algorithm);
+ ?>
+ </td>
+ </tr>
+ <tr>
+ <td>Extensions</td>
+ <td>
+ <div class="panel-group" id="accordion<?php echo bcdechex($cert_data['serialNumber']); ?>" role="tablist" aria-multiselectable="true">
+ <div class="panel panel-default">
+ <div class="panel-heading" role="tab" id="heading<?php echo bcdechex($cert_data['serialNumber']); ?>">
+ <h4 class="panel-title">
+ <a class="collapsed" data-toggle="collapse" data-parent="#accordion" href="#collapse<?php echo bcdechex($cert_data['serialNumber']); ?>" aria-expanded="false" aria-controls="collapse<?php echo bcdechex($cert_data['serialNumber']); ?>">
+ Click to Open/Close
+ </a>
+ </h4>
+ </div>
+ <div id="collapse<?php echo bcdechex($cert_data['serialNumber']); ?>" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading<?php echo bcdechex($cert_data['serialNumber']); ?>">
+ <div class="panel-body">
+ <?php
+ foreach ( $cert_data['extensions'] as $name=>$extension ) {
+ if ( !empty(str_replace(',', " ", "$extension"))) {
+ echo "<strong>" . htmlspecialchars("$name") . "</strong>";
+ echo "<pre>";
+ echo htmlspecialchars($extension);
+ echo "</pre>";
+ }
+ }
+ ?>
+ </div>
+ </div>
+ </div>
+ </div>
</td>
</tr>
+ <?php
+ if(!empty($export_pem)) {
+ ?>
<tr>
- <td>Full Subject</td>
- <td><?php echo htmlspecialchars($cert_data['name']); ?></td>
- </tr>
- <tr>
- <td colspan="2"><strong>Issuer</strong></td>
+ <td>Certificate PEM </td>
+ <td>
+ <div class="panel-group" id="pem-accordion<?php echo bcdechex($cert_data['serialNumber']); ?>" role="tablist" aria-multiselectable="true">
+ <div class="panel panel-default">
+ <div class="panel-heading" role="tab" id="pem-heading<?php echo bcdechex($cert_data['serialNumber']); ?>">
+ <h4 class="panel-title">
+ <a class="collapsed" data-toggle="collapse" data-parent="#accordion" href="#pem-collapse<?php echo bcdechex($cert_data['serialNumber']); ?>" aria-expanded="false" aria-controls="pem-collapse<?php echo bcdechex($cert_data['serialNumber']); ?>">
+ Click to Open/Close
+ </a>
+ </h4>
+ </div>
+ <div id="pem-collapse<?php echo bcdechex($cert_data['serialNumber']); ?>" class="panel-collapse collapse" role="tabpanel" aria-labelledby="pem-heading<?php echo bcdechex($cert_data['serialNumber']); ?>">
+ <div class="panel-body">
+ <?php
+ echo "<pre>";
+ echo htmlspecialchars($export_pem);
+ ?>
+ </pre>
+ </div>
+ </div>
+ </div>
+ </div>
+ </td>
</tr>
- <?php
- if (!empty($cert_data['issuer']) ) {
- foreach ($cert_data['issuer'] as $key => $value) {
- echo "<tr><td>";
- switch ($key) {
- case 'C':
- echo "Country";
- break;
- case 'ST':
- echo "State";
- break;
- case 'L':
- echo "City";
- break;
- case 'O':
- echo "Organization";
- break;
- case 'OU':
- echo "Organizational Unit";
- break;
- case 'CN':
- echo "Common Name";
- break;
- case 'mail':
- echo "Email Address";
- break;
- case 'emailAddress':
- echo "Email Address";
- break;
- default:
- echo htmlspecialchars($key);
- break;
- }
- echo "</td><td>";
- switch ($key) {
- case 'C':
- echo htmlspecialchars($value);
- echo ' <img src="'.htmlspecialchars($current_folder) . 'img/blank.gif" class="flag flag-';
- echo strtolower(htmlspecialchars($value));
- echo '" alt="" />';
- break;
- case 'DC':
- foreach ($value as $key => $value) {
- echo htmlspecialchars($value) . ".";
- }
- break;
- default:
- if (is_array($value)) {
- foreach ($value as $key => $value) {
- echo htmlspecialchars($value) . " ";
- }
- } else {
- echo htmlspecialchars($value);
- }
- break;
- }
- echo "</td></tr>\n";
- }
+ <?php
}
?>
+ <?php
+ if(!empty($key_details['key'])) {
+ ?>
<tr>
- <td colspan="2"><strong>Validity</strong></td>
+ <td>Public Key PEM </td>
+ <td>
+ <div class="panel-group" id="pub-pem-accordion<?php echo bcdechex($cert_data['serialNumber']); ?>" role="tablist" aria-multiselectable="true">
+ <div class="panel panel-default">
+ <div class="panel-heading" role="tab" id="pub-pem-heading<?php echo bcdechex($cert_data['serialNumber']); ?>">
+ <h4 class="panel-title">
+ <a class="collapsed" data-toggle="collapse" data-parent="#accordion" href="#pub-pem-collapse<?php echo bcdechex($cert_data['serialNumber']); ?>" aria-expanded="false" aria-controls="pub-pem-collapse<?php echo bcdechex($cert_data['serialNumber']); ?>">
+ Click to Open/Close
+ </a>
+ </h4>
+ </div>
+ <div id="pub-pem-collapse<?php echo bcdechex($cert_data['serialNumber']); ?>" class="panel-collapse collapse" role="tabpanel" aria-labelledby="pub-pem-heading<?php echo bcdechex($cert_data['serialNumber']); ?>">
+ <div class="panel-body">
+
+ <?php
+ echo "<pre>";
+ echo htmlspecialchars($key_details['key']);
+ ?>
+ </pre>
+ </div>
+ </div>
+ </div>
+ </div>
+ </td>
</tr>
- <?php
- if ( !empty($cert_data['validFrom_time_t']) ) {
- ?>
- <tr>
- <td>Valid From</td>
- <td>
- <?php
- if ( $today < date(DATE_RFC2822,$cert_data['validFrom_time_t']) ) {
- echo '<span class="text-success glyphicon glyphicon-ok-sign"></span>';
- echo '<span class="text-success"> - ';
- } else {
- echo '<span class="text-danger glyphicon glyphicon-exclamation-sign"></span>';
- echo '<span class="text-danger"> - ';
-
- }
- echo htmlspecialchars(date(DATE_RFC2822,$cert_data['validFrom_time_t']));
- echo "</span>";
- ?>
- </td>
- </tr>
-
- <?php
- };
- if ( !empty($cert_data['validTo_time_t']) ) {
- ?>
- <tr>
- <td>Valid Until</td>
- <td>
+ <tr>
+ <td><a href="https://raymii.org/s/articles/HTTP_Public_Key_Pinning_Extension_HPKP.html">SPKI Hash</a></td>
+ <td>
<?php
- if ( strtotime($today) < strtotime(date(DATE_RFC2822,$cert_data['validTo_time_t'])) ) {
- echo '<span class="text-success glyphicon glyphicon-ok-sign"></span>';
- echo '<span class="text-success"> - ';
- } else {
- echo '<span class="text-danger glyphicon glyphicon-exclamation-sign"></span>';
- echo '<span class="text-danger"> - ';
- }
- echo htmlspecialchars(date(DATE_RFC2822,$cert_data['validTo_time_t']));
- echo "</span>";
- ?>
- </td>
- </tr>
- <?php
- };
- if ( !empty($cert_data['extensions']['crlDistributionPoints']) ) {
- ?>
- <tr>
- <td>CRL</td>
- <td>
- <?php
- echo crl_verify($raw_cert_data);
+ $spki_hash = spki_hash($export_pem);
+ print(htmlspecialchars($spki_hash));
?>
- </td>
- </tr>
- <?php
- } else {
- echo "<tr><td>CRL</td><td>No CRL URI found in certificate</td></tr>";
- }
- if ( !empty($cert_data['extensions']['authorityInfoAccess']) && !empty($next_cert_data) ) {
- ?>
- <tr>
- <td>OCSP</td>
- <td>
- <?php
- $ocsp_uri = explode("OCSP - URI:", $cert_data['extensions']['authorityInfoAccess'])[1];
- $ocsp_uri = explode("\n", $ocsp_uri)[0];
- $ocsp_uri = explode(" ", $ocsp_uri)[0];
-
- if ( isset($raw_next_cert_data) && !empty($ocsp_uri) ) {
- if ($ocsp_result["ocsp_verify_status"] == "good") {
- echo '<span class="text-success glyphicon glyphicon-ok-sign"></span> ';
- echo '<span class="text-success"> - OK: ';
- echo htmlspecialchars($ocsp_uri);
- echo "</span><br><pre>This update: " . htmlspecialchars($ocsp_result["This Update"]) . " - ";
- echo "<br>Next update: " . htmlspecialchars($ocsp_result["Next Update"]) . "</pre>";
- } else if ( $ocsp_result["ocsp_verify_status"] == "revoked") {
- echo '<span class="text-danger glyphicon glyphicon-remove-sign"></span>';
- echo '<span class="text-danger"> - REVOKED: ';
- echo htmlspecialchars($ocsp_uri);
- echo "</span><br><pre>This update: " . htmlspecialchars($ocsp_result["This Update"]);
- echo "<br>Next update: " . htmlspecialchars($ocsp_result["Next Update"]);
- echo "<br>Revocation Time: " . htmlspecialchars($ocsp_result["Revocation Time"]);
- echo "<br>Revocation Reason: " . htmlspecialchars($ocsp_result["Reason"]). "</pre>";
- } else {
- echo '<span class="text-danger glyphicon glyphicon-question-sign"></span>';
- echo '<span class="text-danger"> - UNKNOWN: ';
-
- echo " - " . htmlspecialchars($ocsp_uri) . "</span><br>";
- echo "<pre>" . htmlspecialchars($ocsp_result["unknown"]) . "</pre>";
- }
- } else {
- echo "No OCSP URI found in certificate";
- }
- ?>
- </td>
- </tr>
- <?php
- } else {
- echo "<tr><td>OCSP</td><td>No OCSP URI found in certificate</td></tr>";
- }
- if ($is_issuer == false && $csr == false) {
- if ($cert_data['subject']['CN']) {
- echo '<tr><td>Hostname</td>';
- if ( verify_certificate_hostname($raw_cert_data, $host, $port) ) {
- echo "<td><span class='text-success glyphicon glyphicon-ok'></span>\n<span class='text-success'> - ";
- echo htmlspecialchars($host);
- echo " found in CN or SAN.</span></td></tr>";
- } else {
-
- echo '<td><span class="text-danger glyphicon glyphicon-remove"></span><span class="text-danger"> - ';
- echo htmlspecialchars($host);
- echo ' NOT found in CN or SAN.</span></td></tr>';
- }
- }
- } else {
- if ($csr == false) {
- echo "<tr><td>Hostname</td><td>Not applicable, this seems to be a CA signing certificate.</td></tr>";
- } else {
- echo "<tr><td>Hostname</td><td>Not applicable, this seems to be a CSR.</td></tr>";
- }
+ </td>
+ </tr>
+ <?php
}
?>
- <tr>
- <td colspan="2"><strong>Details</strong></td>
- </tr>
- <?php
- if ( !empty($cert_data['purposes']) ) {
- ?>
- <tr>
- <td>Purposes</td>
- <td>
- <?php
- $purposes_len = count($cert_data['purposes']);
- foreach ($cert_data['purposes'] as $key => $purpose) {
- echo htmlspecialchars($purpose[2]);
- if ( $key != $purposes_len - 1) {
- echo ", ";
- }
- }
- ?>
- </td>
- </tr>
- <?php
- };
- if ( !empty($cert_data['serialNumber']) ) {
- ?>
- <tr>
- <td>Serial</td>
- <td><code>
- <?php
- $sn = str_split(strtoupper(bcdechex($cert_data['serialNumber'])), 2);
- $sn_len = count($sn);
- foreach ($sn as $key => $s) {
- echo htmlspecialchars($s);
- if ( $key != $sn_len - 1) {
- echo ":";
- }
- }
- ?>
- </code></td>
- </tr>
- <?php
- }
- ?>
- <tr>
- <td>Key Size / Type</td>
- <td>
- <?php
-
+ </tbody>
+ </table>
+ <?php
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+function csr_parse_json($csr) {
+ $result = array();
+ if (strpos($csr, "BEGIN CERTIFICATE REQUEST") !== false) {
+ $cert_data = openssl_csr_get_public_key($csr);
+ $cert_details = openssl_pkey_get_details($cert_data);
+ $cert_key = $cert_details['key'];
+ $cert_subject = openssl_csr_get_subject($csr);
+ $result["subject"] = $cert_subject;
+ $result["key"] = $cert_key;
+ $result["details"] = $cert_details;
+ } elseif (strpos($csr, "BEGIN CERTIFICATE") !== false) {
+ $result = cert_parse_json($csr);
+ } else {
+ $result = array("error" => "data not valid csr");
+ }
+ return $result;
+}
+
+function cert_parse_json($raw_cert_data, $raw_next_cert_data=null, $host=null, $validate_hostname=false) {
+ global $random_blurp;
+ global $ev_oids;
+ $result = array();
+ $cert_data = openssl_x509_parse($raw_cert_data);
+ if (isset($raw_next_cert_data)) {
+ $next_cert_data = openssl_x509_parse($raw_next_cert_data);
+ }
+ $today = date("Y-m-d");
+ //cert
+ if (isset($cert_data) ) {
+ // purposes
+ $purposes = array();
+ foreach ($cert_data['purposes'] as $key => $purpose) {
+ $purposes[$purpose[2]]["ca"] = $purpose[1];
+ $purposes[$purpose[2]]["general"] = $purpose[0];
+ }
+ unset($cert_data['purposes']);
+ $cert_data['purposes'] = $purposes;
+ $result["cert_data"] = $cert_data;
+ }
+ if ( array_search(explode("Policy: ", explode("\n", $cert_data['extensions']['certificatePolicies'])[0])[1], $ev_oids) ) {
+ $result["validation_type"] = "extended";
+ } else if ( isset($cert_data['subject']['O'] ) ) {
+ $result["validation_type"] = "organisation";
+ } else if ( isset($cert_data['subject']['CN'] ) ) {
+ $result["validation_type"] = "domain";
+ }
+ // crl
+ if (isset($cert_data['extensions']['crlDistributionPoints']) ) {
+ $result["crl"] = crl_verify_json($raw_cert_data);
+ } else {
+ $result["crl"] = "No CRL URI found in certificate";
+ }
+ // ocsp
+ if (isset($cert_data['extensions']['authorityInfoAccess']) && isset($next_cert_data) ) {
+ $ocsp_uris = explode("OCSP - URI:", $cert_data['extensions']['authorityInfoAccess']);
+ unset($ocsp_uris[0]);
+ if ( isset($raw_next_cert_data) && isset($ocsp_uris) ) {
+ foreach ($ocsp_uris as $key => $ocsp_uri) {
+ $ocsp_uri = explode("\n", $ocsp_uri)[0];
+ $ocsp_uri = explode(" ", $ocsp_uri)[0];
+ $result["ocsp"]["$key"] = ocsp_verify_json($raw_cert_data, $raw_next_cert_data, $ocsp_uri);
+ }
+
+ } else {
+ $result["ocsp"] = "No OCSP URI found in certificate";
+ }
+ } else {
+ $result["ocsp"] = "No OCSP URI found in certificate";
+ }
+ // hostname validation
+ if ($validate_hostname == true) {
+ if (isset($cert_data['subject']['CN'])) {
+ if ( verify_certificate_hostname($raw_cert_data, $host) ) {
+ $result["hostname_in_san_or_cn"] = "true";
+ } else {
+ $result["hostname_in_san_or_cn"] = "false";
+ }
+ }
+ } else {
+ $result["hostname_in_san_or_cn"] = "n/a; ca signing certificate";
+ }
+ //serial
+ if ( isset($cert_data['serialNumber']) ) {
+ $serial = "";
+ $sn = str_split(strtoupper(bcdechex($cert_data['serialNumber'])), 2);
+ $sn_len = count($sn);
+ foreach ($sn as $key => $s) {
+ $serial += htmlspecialchars($s);
+ if ( $key != $sn_len - 1) {
+ $serial += ":";
+ }
+ }
+ $result["serial"] = $serial;
+ }
+
+ // key details
+ $key_details = openssl_pkey_get_details(openssl_pkey_get_public($raw_cert_data));
+ $export_pem = "";
+ openssl_x509_export($raw_cert_data, $export_pem);
+ if (isset($key_details['rsa'])) {
+ $result["key"]["type"] = "rsa";
+ $result["key"]["bits"] = $key_details['bits'];
+ } else if (isset($key_details['dsa'])) {
+ $result["key"]["type"] = "dsa";
+ $result["key"]["bits"] = $key_details['bits'];
+ } else if (isset($key_details['dh'])) {
+ $result["key"]["type"] = "dh";
+ $result["key"]["bits"] = $key_details['bits'];
+ } else if (isset($key_details['ec'])) {
+ $result["key"]["type"] = "ecdsa";
+ $result["key"]["bits"] = $key_details['bits'];
+ } else {
+ $result["key"]["type"] = "unknown";
+ $result["key"]["bits"] = $key_details['bits'];
+ }
+ // signature algorithm
+ $result["key"]["signature_algorithm"] = cert_signature_algorithm($raw_cert_data);
+ if(isset($export_pem)) {
+ $result["key"]["certificate_pem"] = $export_pem;
+ }
+ if(isset($key_details['key'])) {
+ $result["key"]["public_key_pem"] = $key_details['key'];
+ $result["key"]["spki_hash"] = spki_hash($export_pem);
+ }
+ return $result;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
- $key_details = openssl_pkey_get_details(openssl_pkey_get_public($raw_cert_data));
- $export_pem = "";
- openssl_x509_export($raw_cert_data, $export_pem);
-
- if ( $key_details['rsa'] ) {
- echo htmlspecialchars($key_details['bits']);
- echo " bits RSA";
- } else if ( $key_details['dsa'] ) {
- echo htmlspecialchars($key_details['bits']);
- echo " bits DSA";
- } else if ( $key_details['dh'] ) {
- echo htmlspecialchars($key_details['bits']);
- echo " bits DH";
- } else {
- echo htmlspecialchars(var_dump($key_details['bits']));
- echo " bits";
- }
- ?>
- </td>
- </tr>
- <tr>
- <td>Signature Algorithm</td>
- <td>
- <?php
- $signature_algorithm = cert_signature_algorithm($raw_cert_data);
- echo htmlspecialchars($signature_algorithm);
- ?>
- </td>
- </tr>
- <tr>
- <td>Extensions</td>
- <td>
- <div class="panel-group" id="accordion<?php echo bcdechex($cert_data['serialNumber']); ?>" role="tablist" aria-multiselectable="true">
- <div class="panel panel-default">
- <div class="panel-heading" role="tab" id="heading<?php echo bcdechex($cert_data['serialNumber']); ?>">
- <h4 class="panel-title">
- <a class="collapsed" data-toggle="collapse" data-parent="#accordion" href="#collapse<?php echo bcdechex($cert_data['serialNumber']); ?>" aria-expanded="false" aria-controls="collapse<?php echo bcdechex($cert_data['serialNumber']); ?>">
- Click to Open/Close
- </a>
- </h4>
- </div>
- <div id="collapse<?php echo bcdechex($cert_data['serialNumber']); ?>" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading<?php echo bcdechex($cert_data['serialNumber']); ?>">
- <div class="panel-body">
- <?php
- foreach ( $cert_data['extensions'] as $name=>$extension ) {
- if ( !empty(str_replace(',', " ", "$extension"))) {
- echo "<strong>" . htmlspecialchars("$name") . "</strong>";
- echo "<pre>";
- echo htmlspecialchars($extension);
- echo "</pre>";
- }
- }
- ?>
- </div>
- </div>
- </div>
- </div>
- </td>
- </tr>
- <?php
- if(!empty($export_pem)) {
- ?>
- <tr>
- <td>Certificate PEM </td>
- <td>
- <div class="panel-group" id="pem-accordion<?php echo bcdechex($cert_data['serialNumber']); ?>" role="tablist" aria-multiselectable="true">
- <div class="panel panel-default">
- <div class="panel-heading" role="tab" id="pem-heading<?php echo bcdechex($cert_data['serialNumber']); ?>">
- <h4 class="panel-title">
- <a class="collapsed" data-toggle="collapse" data-parent="#accordion" href="#pem-collapse<?php echo bcdechex($cert_data['serialNumber']); ?>" aria-expanded="false" aria-controls="pem-collapse<?php echo bcdechex($cert_data['serialNumber']); ?>">
- Click to Open/Close
- </a>
- </h4>
- </div>
- <div id="pem-collapse<?php echo bcdechex($cert_data['serialNumber']); ?>" class="panel-collapse collapse" role="tabpanel" aria-labelledby="pem-heading<?php echo bcdechex($cert_data['serialNumber']); ?>">
- <div class="panel-body">
- <?php
- echo "<pre>";
- echo htmlspecialchars($export_pem);
- ?>
- </pre>
- </div>
- </div>
- </div>
- </div>
- </td>
- </tr>
- <?php
- }
- ?>
- <?php
- if(!empty($key_details['key'])) {
- ?>
- <tr>
- <td>Public Key PEM </td>
- <td>
- <div class="panel-group" id="pub-pem-accordion<?php echo bcdechex($cert_data['serialNumber']); ?>" role="tablist" aria-multiselectable="true">
- <div class="panel panel-default">
- <div class="panel-heading" role="tab" id="pub-pem-heading<?php echo bcdechex($cert_data['serialNumber']); ?>">
- <h4 class="panel-title">
- <a class="collapsed" data-toggle="collapse" data-parent="#accordion" href="#pub-pem-collapse<?php echo bcdechex($cert_data['serialNumber']); ?>" aria-expanded="false" aria-controls="pub-pem-collapse<?php echo bcdechex($cert_data['serialNumber']); ?>">
- Click to Open/Close
- </a>
- </h4>
- </div>
- <div id="pub-pem-collapse<?php echo bcdechex($cert_data['serialNumber']); ?>" class="panel-collapse collapse" role="tabpanel" aria-labelledby="pub-pem-heading<?php echo bcdechex($cert_data['serialNumber']); ?>">
- <div class="panel-body">
-
- <?php
- echo "<pre>";
- echo htmlspecialchars($key_details['key']);
- ?>
- </pre>
- </div>
- </div>
- </div>
- </div>
- </td>
- </tr>
- <tr>
- <td><a href="https://raymii.org/s/articles/HTTP_Public_Key_Pinning_Extension_HPKP.html">SPKI Hash</a></td>
- <td>
- <?php
- $spki_hash = spki_hash($export_pem);
- print(htmlspecialchars($spki_hash));
- ?>
- </td>
- </tr>
- <?php
- }
- ?>
- </tbody>
- </table>
- <?php
- }
?> \ No newline at end of file
diff --git a/functions/textual.php b/functions/textual.php
index b28a764..93a5838 100644
--- a/functions/textual.php
+++ b/functions/textual.php
@@ -14,6 +14,12 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
+function pre_dump($var) {
+ echo "<pre>";
+ var_dump($var);
+ echo "<pre>";
+}
+
function startsWith($haystack, $needle) {
// search backwards starting from haystack length characters from the end
return $needle === "" || strrpos($haystack, $needle, -strlen($haystack)) !== FALSE;
diff --git a/functions/verify_certifitcate.php b/functions/verify_certifitcate.php
index 4e80ea4..86312a1 100644
--- a/functions/verify_certifitcate.php
+++ b/functions/verify_certifitcate.php
@@ -14,7 +14,7 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
-function verify_certificate_hostname($raw_cert, $host, $port) {
+function verify_certificate_hostname($raw_cert, $host) {
$cert_data = openssl_x509_parse($raw_cert);
if ($cert_data['subject']['CN']) {
$cert_host_names = [];
diff --git a/index.php b/index.php
index bdab577..c4ecde0 100644
--- a/index.php
+++ b/index.php
@@ -314,7 +314,7 @@ foreach (glob("functions/*.php") as $filename) {
?>
<div class="footer">
<div class="col-md-6 col-md-offset-1 container">
- <p class="text-muted">By <a href="https://raymii.org/s/software/OpenSSL_Decoder.html">Remy van Elst</a>. License: GNU AGPLv3. <a href="https://github.com/RaymiiOrg/ssl-decoder">Source code</a>. <strong><a href="https://cipherli.st/">Strong SSL Ciphers & Config settings @ Cipherli.st</a></strong>. Version: 2.0</p>
+ <p class="text-muted">By <a href="https://raymii.org/s/software/OpenSSL_Decoder.html">Remy van Elst</a>. License: GNU AGPLv3. <a href="https://github.com/RaymiiOrg/ssl-decoder">Source code</a>. <strong><a href="https://cipherli.st/">Strong SSL Ciphers & Config settings @ Cipherli.st</a></strong>. Version: 2.1</p>
</div>
</div>
</div>
diff --git a/json.php b/json.php
new file mode 100644
index 0000000..11ffef0
--- /dev/null
+++ b/json.php
@@ -0,0 +1,121 @@
+<?php
+error_reporting(E_ALL & ~E_NOTICE);
+foreach (glob("functions/*.php") as $filename) {
+ include $filename;
+}
+
+function utf8encodeNestedArray($arr) {
+ // json_encode fails with binary data. utf-8 encode that first, some ca's like to encode images in their OID's (verisign, 1.3.6.1.5.5.7.1.12)...
+ $encoded_arr = array();
+ foreach ($arr as $key => $value) {
+ if (is_array($value)) {
+ $encoded_arr[utf8_encode($key)] = utf8encodeNestedArray($value);
+ } else {
+ $encoded_arr[utf8_encode($key)] = utf8_encode($value);
+ }
+ }
+ return $encoded_arr;
+}
+
+function check_json($host,$port) {
+ $data = [];
+ $stream = stream_context_create (array("ssl" =>
+ array("capture_peer_cert" => true,
+ "capture_peer_cert_chain" => true,
+ "verify_peer" => false,
+ "verify_peer_name" => false,
+ "allow_self_signed" => true,
+ "capture_session_meta" => true,
+ "sni_enabled" => true)));
+ $read_stream = stream_socket_client("ssl://$host:$port", $errno, $errstr, 2, STREAM_CLIENT_CONNECT, $stream);
+ if ( $read_stream === false ) {
+ $data["error"] = ["Failed to connect: " . htmlspecialchars($errstr)];
+ return $data;
+ } else {
+ $context = stream_context_get_params($read_stream);
+ $context_meta = stream_context_get_options($read_stream)['ssl']['session_meta'];
+ $cert_data = openssl_x509_parse($context["options"]["ssl"]["peer_certificate"]);
+ $chain_data = $context["options"]["ssl"]["peer_certificate_chain"];
+ $chain_length = count($chain_data);
+ if (isset($chain_data) && $chain_length < 10) {
+ $chain_length = count($chain_data);
+ $chain_arr_keys = ($chain_data);
+ foreach(array_keys($chain_arr_keys) as $key) {
+ $curr = $chain_data[$key];
+ $next = $chain_data[$key+1];
+ $prev = $chain_data[$key-1];
+ $chain_key = (string)$key+1;
+ if ($key == 0) {
+ $data["connection"] = ssl_conn_metadata_json($host, $port, $read_stream, $chain_data);
+ $data["chain"][$chain_key] = cert_parse_json($curr, $next, false, $host, true);
+ } else {
+ $data["chain"][$chain_key] = cert_parse_json($curr, $next, false, null, false);
+ }
+ }
+ } else {
+ $data["error"] = ["Chain too long."];
+ return $data;
+ }
+ }
+ return $data;
+}
+
+if ( isset($_GET['host']) && !empty($_GET['host'])) {
+ $data = [];
+ $hostname = mb_strtolower(get($_GET['host']));
+ $host = parse_hostname($hostname);
+ if ($host['port']) {
+ $port = $host['port'];
+ } else {
+ $port = get($_GET['port'], '443');
+ }
+ $host = $host['hostname'];
+ if ( !is_numeric($port) ) {
+ $port = 443;
+ }
+ $data["data"] = check_json($host,$port);
+
+} elseif(isset($_GET['csr']) && !empty($_GET['csr'])) {
+ $data["data"]["chain"]["1"] = csr_parse_json($_GET['csr']);
+
+} else {
+ $data["error"] = ["Host is required"];
+
+}
+
+$data = utf8encodeNestedArray($data);
+
+if(isset($data["data"]["error"])) {
+ $data["error"] = $data["data"]["error"];
+ unset($data["data"]);
+}
+
+if ($_GET["type"] == "pretty") {
+ header('Content-Type: text/html');
+ echo "<pre>";
+ echo htmlspecialchars(json_encode($data,JSON_PRETTY_PRINT));
+ echo "</pre>";
+ ?>
+ <!-- Piwik -->
+ <script type="text/javascript">
+ var _paq = _paq || [];
+ _paq.push(['trackPageView']);
+ _paq.push(['enableLinkTracking']);
+ (function() {
+ var u="//hosted-oswa.org/piwik/";
+ _paq.push(['setTrackerUrl', u+'piwik.php']);
+ _paq.push(['setSiteId', 34]);
+ var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
+ g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s);
+ })();
+ </script>
+ <noscript><p><img src="//hosted-oswa.org/piwik/piwik.php?idsite=34" style="border:0;" alt="" /></p></noscript>
+ <!-- End Piwik Code -->
+ <?
+} else {
+ header('Content-Type: application/json');
+ echo json_encode($data);
+}
+
+?>
+