diff options
author | Remy <relst@relst.nl> | 2015-03-30 12:26:17 +0200 |
---|---|---|
committer | Remy <relst@relst.nl> | 2015-03-30 12:26:17 +0200 |
commit | b470f3e3cb6fd341da0b4eed465d6165d98cd441 (patch) | |
tree | 5123b500c9d774cd2e2d6d961359343346d7a4f3 | |
parent | faa7f20fcc89bb1a1b77f2aaa78b88cda794b1b5 (diff) | |
download | ssl-decoder-b470f3e3cb6fd341da0b4eed465d6165d98cd441.zip ssl-decoder-b470f3e3cb6fd341da0b4eed465d6165d98cd441.tar.gz ssl-decoder-b470f3e3cb6fd341da0b4eed465d6165d98cd441.tar.bz2 |
Add json endpoint
-rw-r--r-- | CHANGELOG.md | 5 | ||||
-rw-r--r-- | README.md | 560 | ||||
-rw-r--r-- | functions/connection.php | 1229 | ||||
-rw-r--r-- | functions/crl.php | 79 | ||||
-rw-r--r-- | functions/ocsp.php | 209 | ||||
-rw-r--r-- | functions/parse_certificate.php | 1362 | ||||
-rw-r--r-- | functions/textual.php | 6 | ||||
-rw-r--r-- | functions/verify_certifitcate.php | 2 | ||||
-rw-r--r-- | index.php | 2 | ||||
-rw-r--r-- | json.php | 121 |
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 @@ -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> </h1></td>'; - } else { - echo '<td><h1><span class="text-danger glyphicon glyphicon-remove"></span> </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> </h1></td>'; } else { echo '<td><h1><span class="text-danger glyphicon glyphicon-remove"></span> </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> </h1></td>'; + } else { + echo '<td><h1><span class="text-danger glyphicon glyphicon-remove"></span> </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> </h1></td>'; - } else { - echo '<td><h1><span class="text-danger glyphicon glyphicon-remove"></span> </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> </h1></td>'; + } else { + echo '<td><h1><span class="text-danger glyphicon glyphicon-remove"></span> </h1></td>'; + } + } else { + echo '<td> </td>'; + } +// crl + if ( !empty($cert_data['extensions']['crlDistributionPoints']) ) { + echo "<td><h1>" . crl_verify($raw_cert_data, false) . " </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> </h1>'; + } else if ($ocsp_result["ocsp_verify_status"] == "revoked") { + echo '<h1><span class="text-danger glyphicon glyphicon-remove"></span> </h1>'; + } else { + echo '<h1><span class="text-danger glyphicon glyphicon-question-sign"></span> </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) . " </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> </h1>'; - } else if ($ocsp_result["ocsp_verify_status"] == "revoked") { - echo '<h1><span class="text-danger glyphicon glyphicon-remove"></span> </h1>'; - } else { - echo '<h1><span class="text-danger glyphicon glyphicon-question-sign"></span> </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 = []; @@ -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); +} + +?> + |