+
[0x00] | NULL-MD5 | RSA(512) | None | None, export | TLS_NULL_WITH_NULL_NULL |
[0x01] | NULL-MD5 | RSA | None | None | TLS_RSA_WITH_NULL_MD5 |
[0x02] | NULL-SHA | RSA | None | None | TLS_RSA_WITH_NULL_SHA |
@@ -54,9 +65,13 @@ td { border:1px solid #999; }
[0x19] | EXP-ADH-DES-CBC-SHA | DH(512) | DES | 40, export | TLS_DH_anon_EXPORT_WITH_DES40_CBC_SHA |
[0x1a] | ADH-DES-CBC-SHA | DH | DES | 56 | TLS_DH_anon_WITH_DES_CBC_SHA |
[0x1b] | ADH-DES-CBC3-SHA | DH | 3DES | 168 | TLS_DH_anon_WITH_3DES_EDE_CBC_SHA |
+
+
[0x1c] | | FORTEZZA | None | None | SSL_FORTEZZA_KEA_WITH_NULL_SHA |
[0x1d] | | FORTEZZA | FORTEZZA_CBC | 80 | SSL_FORTEZZA_KEA_WITH_FORTEZZA_CBC_SHA |
[0x1e] | | FORTEZZA | FORTEZZA_RC4 | 128 | SSL_FORTEZZA_KEA_WITH_RC4_128_SHA |
+
+
[0x1e] | KRB5-DES-CBC-SHA | KRB5 | DES | 56 | TLS_KRB5_WITH_DES_CBC_SHA |
[0x1f] | KRB5-DES-CBC3-SHA | KRB5 | 3DES | 168 | TLS_KRB5_WITH_3DES_EDE_CBC_SHA |
[0x20] | KRB5-RC4-SHA | KRB5 | RC4 | 128 | TLS_KRB5_WITH_RC4_128_SHA |
@@ -71,6 +86,13 @@ td { border:1px solid #999; }
[0x29] | EXP-KRB5-DES-CBC-MD5 | KRB5 | DES | 40, export | TLS_KRB5_EXPORT_WITH_DES_CBC_40_MD5 |
[0x2a] | EXP-KRB5-RC2-CBC-MD5 | KRB5 | RC2 | 40, export | TLS_KRB5_EXPORT_WITH_RC2_CBC_40_MD5 |
[0x2b] | EXP-KRB5-RC4-MD5 | KRB5 | RC4 | 40, export | TLS_KRB5_EXPORT_WITH_RC4_40_MD5 |
+
+
+ [0x2c] | EXP-KRB5-RC4-MD5 | PSK | None | None | TLS_PSK_WITH_NULL_SHA |
+ [0x2d] | EXP-KRB5-RC4-MD5 | DH/PSK | None | None | TLS_DHE_PSK_WITH_NULL_SHA |
+ [0x2e] | EXP-KRB5-RC4-MD5 | RSA/PSK | None | None | TLS_RSA_PSK_WITH_NULL_SHA |
+
+
[0x2f] | AES128-SHA | RSA | AES | 128 | TLS_RSA_WITH_AES_128_CBC_SHA |
[0x30] | DH-DSS-AES128-SHA | DH/DSS | AES | 128 | TLS_DH_DSS_WITH_AES_128_CBC_SHA |
[0x31] | DH-RSA-AES128-SHA | DH/RSA | AES | 128 | TLS_DH_RSA_WITH_AES_128_CBC_SHA |
@@ -89,6 +111,8 @@ td { border:1px solid #999; }
[0x3e] | DH-DSS-AES128-SHA256 | DH/DSS | AES | 128 | TLS_DH_DSS_WITH_AES_128_CBC_SHA256 |
[0x3f] | DH-RSA-AES128-SHA256 | DH/RSA | AES | 128 | TLS_DH_RSA_WITH_AES_128_CBC_SHA256 |
[0x40] | DHE-DSS-AES128-SHA256 | DH | AES | 128 | TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 |
+
+
[0x41] | CAMELLIA128-SHA | RSA | Camellia | 128 | TLS_RSA_WITH_CAMELLIA_128_CBC_SHA |
[0x42] | DH-DSS-CAMELLIA128-SHA | DH/DSS | Camellia | 128 | TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA |
[0x43] | DH-RSA-CAMELLIA128-SHA | DH/RSA | Camellia | 128 | TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA |
@@ -96,7 +120,8 @@ td { border:1px solid #999; }
[0x45] | DHE-RSA-CAMELLIA128-SHA | DH | Camellia | 128 | TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA |
[0x46] | ADH-CAMELLIA128-SHA | DH | Camellia | 128 | TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA |
-
+ [0x60] | EXP1024-RC4-MD5 | RSA(1024) | RC4 | 56, export | TLS_RSA_EXPORT1024_WITH_RC4_56_MD5 |
+ [0x61] | EXP1024-RC2-CBC-MD5 | RSA(1024) | RC2 | 56, export | TLS_RSA_EXPORT1024_WITH_RC2_CBC_56_MD5 |
[0x62] | EXP1024-DES-CBC-SHA | RSA(1024) | DES | 56, export | TLS_RSA_EXPORT1024_WITH_DES_CBC_SHA |
[0x63] | EXP1024-DHE-DSS-DES-CBC-SHA | DH(1024) | DES | 56, export | TLS_DHE_DSS_EXPORT1024_WITH_DES_CBC_SHA |
[0x64] | EXP1024-RC4-SHA | RSA(1024) | RC4 | 56, export | TLS_RSA_EXPORT1024_WITH_RC4_56_SHA |
@@ -109,21 +134,26 @@ td { border:1px solid #999; }
[0x6b] | DHE-RSA-AES256-SHA256 | DH | AES | 256 | TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 |
[0x6c] | ADH-AES128-SHA256 | DH | AES | 128 | TLS_DH_anon_WITH_AES_128_CBC_SHA256 |
[0x6d] | ADH-AES256-SHA256 | DH | AES | 256 | TLS_DH_anon_WITH_AES_256_CBC_SHA256 |
- [0x80] | GOST94-GOST89-GOST89 | GOST | GOST89 | 256 | TLS_GOSTR341094_WITH_28147_CNT_IMIT |
- [0x81] | GOST2001-GOST89-GOST89 | GOST | GOST89 | 256 | TLS_GOSTR341001_WITH_28147_CNT_IMIT |
- [0x82] | GOST94-NULL-GOST94 | GOST | eNULL | None | TLS_GOSTR341001_WITH_NULL_GOSTR3411 |
- [0x83] | GOST2001-GOST89-GOST89 | GOST | eNULL | None | TLS_GOSTR341094_WITH_NULL_GOSTR3411 |
+
+
+ [0x80] | GOST94-GOST89-GOST89 | VKO GOST 34.10-94 | GOST89 | 256 | TLS_GOSTR341094_WITH_28147_CNT_IMIT |
+ [0x81] | GOST2001-GOST89-GOST89 | VKO GOST 34.10-2001 | GOST89 | 256 | TLS_GOSTR341001_WITH_28147_CNT_IMIT |
+ [0x82] | GOST94-NULL-GOST94 | VKO GOST 34.10-94 | eNULL | None | TLS_GOSTR341001_WITH_NULL_GOSTR3411 |
+ [0x83] | GOST2001-GOST89-GOST89 | VKO GOST 34.10-2001 | eNULL | None | TLS_GOSTR341094_WITH_NULL_GOSTR3411 |
+
+
[0x84] | CAMELLIA256-SHA | RSA | Camellia | 256 | TLS_RSA_WITH_CAMELLIA_256_CBC_SHA |
[0x85] | DH-DSS-CAMELLIA256-SHA | DH/DSS | Camellia | 256 | TLS_DH_DSS_WITH_CAMELLIA_256_CBC_SHA |
[0x86] | DH-RSA-CAMELLIA256-SHA | DH/RSA | Camellia | 256 | TLS_DH_RSA_WITH_CAMELLIA_256_CBC_SHA |
[0x87] | DHE-DSS-CAMELLIA256-SHA | DH | Camellia | 256 | TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA |
[0x88] | DHE-RSA-CAMELLIA256-SHA | DH | Camellia | 256 | TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA |
[0x89] | ADH-CAMELLIA256-SHA | DH | Camellia | 256 | TLS_DH_anon_WITH_CAMELLIA_256_CBC_SHA |
+
+
[0x8a] | PSK-RC4-SHA | PSK | RC4 | 128 | TLS_PSK_WITH_RC4_128_SHA |
[0x8b] | PSK-3DES-EDE-CBC-SHA | PSK | 3DES | 168 | TLS_PSK_WITH_3DES_EDE_CBC_SHA |
[0x8c] | PSK-AES128-CBC-SHA | PSK | AES | 128 | TLS_PSK_WITH_AES_128_CBC_SHA |
[0x8d] | PSK-AES256-CBC-SHA | PSK | AES | 256 | TLS_PSK_WITH_AES_256_CBC_SHA |
-
[0x8e] | | PSK/DHE | RC4 | 128 | TLS_DHE_PSK_WITH_RC4_128_SHA |
[0x8f] | | PSK/DHE | 3DES | 168 | TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA |
[0x90] | | PSK/DHE | AES | 128 | TLS_DHE_PSK_WITH_AES_128_CBC_SHA |
@@ -133,12 +163,15 @@ td { border:1px solid #999; }
[0x94] | | PSK/RSA | AES | 128 | TLS_RSA_PSK_WITH_AES_128_CBC_SHA |
[0x95] | | PSK/RSA | AES | 256 | TLS_RSA_PSK_WITH_AES_256_CBC_SHA |
+
[0x96] | SEED-SHA | RSA | SEED | 128 | TLS_RSA_WITH_SEED_CBC_SHA |
[0x97] | DH-DSS-SEED-SHA | DH/DSS | SEED | 128 | TLS_DH_DSS_WITH_SEED_CBC_SHA |
[0x98] | DH-RSA-SEED-SHA | DH/RSA | SEED | 128 | TLS_DH_RSA_WITH_SEED_CBC_SHA |
[0x99] | DHE-DSS-SEED-SHA | DH | SEED | 128 | TLS_DHE_DSS_WITH_SEED_CBC_SHA |
[0x9a] | DHE-RSA-SEED-SHA | DH | SEED | 128 | TLS_DHE_RSA_WITH_SEED_CBC_SHA |
[0x9b] | ADH-SEED-SHA | DH | SEED | 128 | TLS_DH_anon_WITH_SEED_CBC_SHA |
+
+
[0x9c] | AES128-GCM-SHA256 | RSA | AESGCM | 128 | TLS_RSA_WITH_AES_128_GCM_SHA256 |
[0x9d] | AES256-GCM-SHA384 | RSA | AESGCM | 256 | TLS_RSA_WITH_AES_256_GCM_SHA384 |
[0x9e] | DHE-RSA-AES128-GCM-SHA256 | DH | AESGCM | 128 | TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 |
@@ -152,8 +185,47 @@ td { border:1px solid #999; }
[0xa6] | ADH-AES128-GCM-SHA256 | DH | AESGCM | 128 | TLS_DH_anon_WITH_AES_128_GCM_SHA256 |
[0xa7] | ADH-AES256-GCM-SHA384 | DH | AESGCM | 256 | TLS_DH_anon_WITH_AES_256_GCM_SHA384 |
- [0x5600] | TLS_FALLBACK_SCSV | | | | TLS_FALLBACK_SCSV |
+
+
+
+
+ [0xba] | CAMELLIA128-SHA256 | RSA | Camellia | 128 | TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 |
+ [0xbb] | DH-DSS-CAMELLIA128-SHA256 | DH/DSS | Camellia | 128 | TLS_DH_DSS_WITH_CAMELLIA_128_CBC_SHA256 |
+ [0xbc] | DH-RSA-CAMELLIA128-SHA256 | DH/RSA | Camellia | 128 | TLS_DH_RSA_WITH_CAMELLIA_128_CBC_SHA256 |
+ [0xbd] | DHE-DSS-CAMELLIA128-SHA256 | DH | Camellia | 128 | TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA256 |
+ [0xbe] | DHE-RSA-CAMELLIA128-SHA256 | DH | Camellia | 128 | TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 |
+ [0xbf] | ADH-CAMELLIA128-SHA256 | DH | Camellia | 128 | TLS_DH_anon_WITH_CAMELLIA_128_CBC_SHA256 |
+
+
+ [0x5600] | TLS_FALLBACK_SCSV | | | | TLS_EMPTY_RENEGOTIATION_INFO_SCSV |
+
+
[0xc001] | ECDH-ECDSA-NULL-SHA | ECDH/ECDSA | None | None | TLS_ECDH_ECDSA_WITH_NULL_SHA |
[0xc002] | ECDH-ECDSA-RC4-SHA | ECDH/ECDSA | RC4 | 128 | TLS_ECDH_ECDSA_WITH_RC4_128_SHA |
[0xc003] | ECDH-ECDSA-DES-CBC3-SHA | ECDH/ECDSA | 3DES | 168 | TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA |
@@ -179,6 +251,8 @@ td { border:1px solid #999; }
[0xc017] | AECDH-DES-CBC3-SHA | ECDH | 3DES | 168 | TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA |
[0xc018] | AECDH-AES128-SHA | ECDH | AES | 128 | TLS_ECDH_anon_WITH_AES_128_CBC_SHA |
[0xc019] | AECDH-AES256-SHA | ECDH | AES | 256 | TLS_ECDH_anon_WITH_AES_256_CBC_SHA |
+
+
[0xc01a] | SRP-3DES-EDE-CBC-SHA | SRP | 3DES | 168 | TLS_SRP_SHA_WITH_3DES_EDE_CBC_SHA |
[0xc01b] | SRP-RSA-3DES-EDE-CBC-SHA | SRP | 3DES | 168 | TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA |
[0xc01c] | SRP-DSS-3DES-EDE-CBC-SHA | SRP | 3DES | 168 | TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA |
@@ -188,6 +262,8 @@ td { border:1px solid #999; }
[0xc020] | SRP-AES-256-CBC-SHA | SRP | AES | 256 | TLS_SRP_SHA_WITH_AES_256_CBC_SHA |
[0xc021] | SRP-RSA-AES-256-CBC-SHA | SRP | AES | 256 | TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA |
[0xc022] | SRP-DSS-AES-256-CBC-SHA | SRP | AES | 256 | TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA |
+
+
[0xc023] | ECDHE-ECDSA-AES128-SHA256 | ECDH | AES | 128 | TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 |
[0xc024] | ECDHE-ECDSA-AES256-SHA384 | ECDH | AES | 256 | TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 |
[0xc025] | ECDH-ECDSA-AES128-SHA256 | ECDH/ECDSA | AES | 128 | TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 |
@@ -205,6 +281,7 @@ td { border:1px solid #999; }
[0xc031] | ECDH-RSA-AES128-GCM-SHA256 | ECDH/RSA | AESGCM | 128 | TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 |
[0xc032] | ECDH-RSA-AES256-GCM-SHA384 | ECDH/RSA | AESGCM | 256 | TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 |
+
[0xc033] | ECDHE-PSK-RC4-SHA | PSK/ECDHE | RC4 | 128 | TLS_ECDHE_PSK_WITH_RC4_128_SHA |
[0xc034] | ECDHE-PSK-3DES-EDE-CBC-SHA | PSK/ECDHE | 3DES | 168 | TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA |
[0xc035] | ECDHE-PSK-AES128-CBC-SHA | PSK/ECDHE | AES | 128 | TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA |
@@ -214,6 +291,8 @@ td { border:1px solid #999; }
[0xc039] | ECDHE-PSK-NULL-SHA | PSK/ECDHE | None | None | TLS_ECDHE_PSK_WITH_NULL_SHA |
[0xc03A] | ECDHE-PSK-NULL-SHA256 | PSK/ECDHE | None | None | TLS_ECDHE_PSK_WITH_NULL_SHA256 |
[0xc03B] | ECDHE-PSK-NULL-SHA384 | PSK/ECDHE | None | None | TLS_ECDHE_PSK_WITH_NULL_SHA384 |
+
+
[0xc03C] | | | | | TLS_RSA_WITH_ARIA_128_CBC_SHA256 |
[0xc03D] | | | | | TLS_RSA_WITH_ARIA_256_CBC_SHA384 |
[0xc03E] | | | | | TLS_DH_DSS_WITH_ARIA_128_CBC_SHA256 |
@@ -269,6 +348,7 @@ td { border:1px solid #999; }
[0xc070] | | | | | TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 |
[0xc071] | | | | | TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 |
+
[0xc072] | ECDHE-ECDSA-CAMELLIA128-SHA256 | ECDH | Camellia | 128 | TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 |
[0xc073] | ECDHE-ECDSA-CAMELLIA256-SHA38 | ECDH | Camellia | 256 | TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 |
[0xc074] | ECDH-ECDSA-CAMELLIA128-SHA256 | ECDH/ECDSA | Camellia | 128 | TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 |
@@ -303,15 +383,16 @@ td { border:1px solid #999; }
[0xc091] | | | | | TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 |
[0xc092] | | | | | TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 |
[0xc093] | | | | | TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 |
- [0xc094] | | | | | TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 |
- [0xc095] | | | | | TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 |
- [0xc096] | | | | | TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 |
- [0xc097] | | | | | TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 |
- [0xc098] | | | | | TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 |
- [0xc099] | | | | | TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 |
- [0xc09A] | | | | | TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 |
- [0xc09B] | | | | | TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 |
+ [0xc094] | PSK-CAMELLIA128-SHA256 | PSK | CAMELLIA | 128 | TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 |
+ [0xc095] | PSK-CAMELLIA256-SHA384 | PSK | CAMELLIA | 256 | TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 |
+ [0xc096] | DHE-PSK-CAMELLIA128-SHA256 | PSK/DHE | CAMELLIA | 128 | TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 |
+ [0xc097] | DHE-PSK-CAMELLIA256-SHA384 | PSK/DHE | CAMELLIA | 256 | TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 |
+ [0xc098] | RSA-PSK-CAMELLIA128-SHA256 | PSK/RSA | CAMELLIA | 128 | TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 |
+ [0xc099] | RSA-PSK-CAMELLIA256-SHA384 | PSK/RSA | CAMELLIA | 256 | TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 |
+ [0xc09A] | ECDHE-PSK-CAMELLIA128-SHA25 | PSK/ECDHE | CAMELLIA | 128 | TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 |
+ [0xc09B] | ECDHE-PSK-CAMELLIA256-SHA38 | PSK/ECDHE | CAMELLIA | 256 | TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 |
+
[0xc09c] | AES128-CCM | RSA | AESCCM | 128 | TLS_RSA_WITH_AES_128_CCM |
[0xc09d] | AES256-CCM | RSA | AESCCM | 256 | TLS_RSA_WITH_AES_256_CCM |
[0xc09e] | DHE-RSA-AES128-CCM | DH | AESCCM | 128 | TLS_DHE_RSA_WITH_AES_128_CCM |
@@ -328,6 +409,8 @@ td { border:1px solid #999; }
[0xc0a9] | PSK-AES256-CCM8 | PSK | AESCCM | 256 | TLS_PSK_WITH_AES_256_CCM_8 |
[0xc0aa] | DHE-PSK-AES128-CCM8 | PSK/DHE | AESCCM | 128 | TLS_PSK_DHE_WITH_AES_128_CCM_8 |
[0xc0ab] | DHE-PSK-AES256-CCM8 | PSK/DHE | AESCCM | 256 | TLS_PSK_DHE_WITH_AES_256_CCM_8 |
+
+
[0xc0ac] | ECDHE-ECDSA-AES128-CCM | ECDH | AESCCM | 128 | TLS_ECDHE_ECDSA_WITH_AES_128_CCM |
[0xc0ad] | ECDHE-ECDSA-AES256-CCM | ECDH | AESCCM | 256 | TLS_ECDHE_ECDSA_WITH_AES_256_CCM |
[0xc0ae] | ECDHE-ECDSA-AES128-CCM8 | ECDH | AESCCM | 128 | TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 |
@@ -341,8 +424,31 @@ td { border:1px solid #999; }
[0xff01] | GOST-GOST94 | RSA | GOST89 | 256 | TLS_RSA_WITH_28147_CNT_GOST94 |
[0xff02] | GOST-GOST89MAC | RSA | GOST89 | 256 |
[0xff03] | GOST-GOST89STREAM | RSA | GOST89 | 256 |
+
+
+ [0xfefe] | | RSA | DES | 56 | SSL_RSA_FIPS_WITH_DES_CBC_SHA |
+ [0xfeff] | | RSA | 3DES | 168 | SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA |
+
+ [0xfee0] | | RSA | 3DES | 168 | SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA |
+ [0xfee1] | | RSA | DES | 56 | SSL_RSA_FIPS_WITH_DES_CBC_SHA |
+
[0x010080] | RC4-MD5 | RSA | RC4 | 128 | SSL_CK_RC4_128_WITH_MD5 |
[0x020080] | EXP-RC4-MD5 | RSA(512) | RC4 | 40, export | SSL_CK_RC4_128_EXPORT40_WITH_MD5 |
+
[0x030080] | RC2-CBC-MD5 | RSA | RC2 | 128 | SSL_CK_RC2_128_CBC_WITH_MD5 |
[0x040080] | EXP-RC2-CBC-MD5 | RSA(512) | RC2 | 40, export | SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5 |
[0x050080] | IDEA-CBC-MD5 | RSA | IDEA | 128 | SSL_CK_IDEA_128_CBC_WITH_MD5 |
diff --git a/testssl.sh b/testssl.sh
index 459c055..2ee8b96 100755
--- a/testssl.sh
+++ b/testssl.sh
@@ -135,6 +135,7 @@ declare -x OPENSSL
COLOR=${COLOR:-2} # 2: Full color, 1: b/w+positioning, 0: no ESC at all
COLORBLIND=${COLORBLIND:-false} # if true, swap blue and green in the output
SHOW_EACH_C=${SHOW_EACH_C:-0} # where individual ciphers are tested show just the positively ones tested #FIXME: upside down value
+SHOW_SIGALGO=${SHOW_SIGALGO:-false} # "secret" switch weher testssl.sh shows the signature algorithm for -E / -e
SNEAKY=${SNEAKY:-false} # is the referer and useragent we leave behind just usual?
QUIET=${QUIET:-false} # don't output the banner. By doing this yiu acknowledge usage term appearing in the banner
SSL_NATIVE=${SSL_NATIVE:-false} # we do per default bash sockets where possible "true": switch back to "openssl native"
@@ -368,6 +369,9 @@ pr_headlineln() { pr_headline "$1" ; outln; }
pr_squoted() { out "'$1'"; }
pr_dquoted() { out "\"$1\""; }
+local_problem_ln() { pr_litemagentaln "Local problem: $1"; }
+local_problem() { pr_litemagenta "Local problem: $1"; }
+
### color switcher (see e.g. https://linuxtidbits.wordpress.com/2008/08/11/output-color-on-bash-scripts/
### http://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x405.html
set_color_functions() {
@@ -449,23 +453,22 @@ fileout_footer() {
}
fileout() { # ID, SEVERITY, FINDING
- local finding="$5"
+ local finding=$(strip_lf "$(newline_to_spaces "$(strip_quote "$3")")")
if "$do_json"; then
"$FIRST_FINDING" || echo "," >> $JSONFILE
- finding=$(strip_quote "$3")
echo -e "
{
- 'id' : '$1',
- 'ip' : '$NODE/$NODEIP',
- 'port' : '$PORT',
- 'severity' : '$2',
- 'finding' : '$finding'
+ \"id\" : \"$1\",
+ \"ip\" : \"$NODE/$NODEIP\",
+ \"port\" : \"$PORT\",
+ \"severity\" : \"$2\",
+ \"finding\" : \"$finding\"
}" >> $JSONFILE
fi
# does the following do any sanitization?
if "$do_csv"; then
- echo -e \""$1\"",\"$NODE/$NODEIP\",\"$PORT"\",\""$2"\",\"$(strip_quote "$3")\"" >>$CSVFILE
+ echo -e \""$1\"",\"$NODE/$NODEIP\",\"$PORT"\",\""$2"\",\""$finding"\"" >>$CSVFILE
fi
"$FIRST_FINDING" && FIRST_FINDING=false
}
@@ -1280,8 +1283,13 @@ prettyprint_local() {
local hexcode dash ciph sslvers kx auth enc mac export
local re='^[0-9A-Fa-f]+$'
+ if [[ "$1" == 0x* ]] || [[ "$1" == 0X* ]]; then
+ fatal "pls supply x instead" 2
+ fi
+
pr_headline " Displaying all local ciphers ";
if [[ -n "$1" ]]; then
+ # pattern provided; which one?
[[ $1 =~ $re ]] && \
pr_headline "matching number pattern \"$1\" " || \
pr_headline "matching word pattern "\"$1\"" (ignore case) "
@@ -1384,7 +1392,7 @@ std_cipherlists() {
tmpfile_handle $FUNCNAME.$debugname.txt
else
singlespaces=$(echo "$2" | sed -e 's/ \+/ /g' -e 's/^ //' -e 's/ $//g' -e 's/ //g')
- local_problem "No $singlespaces configured in $OPENSSL"
+ local_problem_ln "No $singlespaces configured in $OPENSSL"
fileout "std_$4" "WARN" "Cipher $2 ($1) not supported by local OpenSSL ($OPENSSL)"
fi
# we need 1xlf in those cases:
@@ -1582,8 +1590,12 @@ run_allciphers(){
available="not a/v"
fi
fi
+ if "$SHOW_SIGALGO"; then
+ $OPENSSL x509 -noout -text -in $TMPFILE | awk -F':' '/Signature Algorithm/ { print $2 }' | head -1
+ else
+ outln
+ fi
fileout "cipher_$HEXC" "INFO" "$(neat_list "$HEXC" "$ciph" "$kx" "$enc") $available"
- outln
tmpfile_handle $FUNCNAME.txt
done
outln
@@ -1628,7 +1640,11 @@ run_cipher_per_proto(){
available="not a/v"
fi
fi
- outln
+ if "$SHOW_SIGALGO"; then
+ $OPENSSL x509 -noout -text -in $TMPFILE | awk -F':' '/Signature Algorithm/ { print $2 }' | head -1
+ else
+ outln
+ fi
id="cipher$proto"
id+="_$HEXC"
fileout "$id" "INFO" "$proto_text $(neat_list "$HEXC" "$ciph" "$kx" "$enc") $available"
@@ -2040,7 +2056,7 @@ run_client_simulation() {
locally_supported() {
[[ -n "$2" ]] && out "$2 "
if $OPENSSL s_client "$1" 2>&1 | grep -aq "unknown option"; then
- local_problem "$OPENSSL doesn't support \"s_client $1\""
+ local_problem_ln "$OPENSSL doesn't support \"s_client $1\""
return 7
fi
return 0
@@ -2107,8 +2123,8 @@ run_protocols() {
using_sockets=false
else
using_sockets=true
- pr_headlineln "(via sockets except TLS 1.2 and SPDY/HTTP2) "
- via+="via sockets except for TLS1.1 and SPDY/HTTP2"
+ pr_headlineln "(via sockets except TLS 1.2, SPDY+HTTP2) "
+ via+="via sockets except for TLS1.2, SPDY+HTTP2"
fi
fi
outln
@@ -2546,7 +2562,7 @@ run_server_preference() {
}
cipher_pref_check() {
- local p proto protos
+ local p proto protos npn_protos
local tested_cipher cipher order
pr_bold " Cipher order"
@@ -2579,8 +2595,8 @@ cipher_pref_check() {
if ! spdy_pre " SPDY/NPN: "; then # is NPN/SPDY supported and is this no STARTTLS?
outln
else
- protos=$($OPENSSL s_client -host $NODE -port $PORT $BUGS -nextprotoneg \"\" >$ERRFILE | grep -a "^Protocols " | sed -e 's/^Protocols.*server: //' -e 's/,//g')
- for p in $protos; do
+ npn_protos=$($OPENSSL s_client -host $NODE -port $PORT $BUGS -nextprotoneg \"\" >$ERRFILE | grep -a "^Protocols " | sed -e 's/^Protocols.*server: //' -e 's/,//g')
+ for p in $npn_protos; do
order=""
$OPENSSL s_client -host $NODE -port $PORT $BUGS -nextprotoneg "$p" $PROXY >$ERRFILE >$TMPFILE
cipher=$(grep -aw "Cipher" $TMPFILE | egrep -avw "New|is" | sed -e 's/^.*Cipher.*://' -e 's/ //g')
@@ -2610,12 +2626,13 @@ cipher_pref_check() {
get_host_cert() {
local tmpvar=$TEMPDIR/$FUNCNAME.txt # change later to $TMPFILE
- $OPENSSL s_client $STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY $SNI $1 2>/dev/null $TEMPDIR/$FUNCNAME.txt
+ $OPENSSL s_client $STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY $SNI $1 2>/dev/null $tmpdir
if sclient_connect_successful $? $tmpvar; then
awk '/-----BEGIN/,/-----END/ { print $0 }' $tmpvar >$HOSTCERT
else
return 1
fi
+ tmpfile_handle $FUNCNAME.txt
# return $((${PIPESTATUS[0]} + ${PIPESTATUS[1]}))
}
@@ -2640,7 +2657,7 @@ verify_retcode_helper() {
}
determine_trust() {
- local heading=$1
+ local json_prefix=$1
local -i i=1
local -i num_ca_bundles=0
local bundle_fname
@@ -2651,24 +2668,24 @@ determine_trust() {
local some_ok=false
local code
local ca_bundles="$INSTALL_DIR/etc/*.pem"
- local spaces=" "
+ local spaces=" "
local -i certificates_provided=1+$(grep -c "\-\-\-\-\-BEGIN CERTIFICATE\-\-\-\-\-" $TEMPDIR/intermediatecerts.pem)
local addtl_warning
+
+ # If $json_prefix is not empty, then there is more than one certificate
+ # and the output should should be indented by two more spaces.
+ [[ -n $json_prefix ]] && spaces=" "
if [[ $OSSL_VER_MAJOR.$OSSL_VER_MINOR == "1.1.0" ]]; then
- pr_litemagentaln "Your $OPENSSL is too new, needed is version 1.0.2"
- out "$spaces"
- fileout "$heading trust" "WARN" "Your $OPENSSL is too new, need version 1.0.2 to determine trust"
- return 7
+ addtl_warning="(Your openssl 1.1.0 might be too new for a reliable check)"
+ fileout "${json_prefix}trust" "WARN" "Your $OPENSSL is too new, need version 1.0.2 to determine trust"
elif [[ $OSSL_VER_MAJOR.$OSSL_VER_MINOR != "1.0.2" ]]; then
- pr_litemagentaln "Your $OPENSSL is too old, needed is version >=1.0.2"
- out "$spaces"
- addtl_warning="Your $OPENSSL is too old, need version 1.0.2 to determine trust. Results may be unreliable."
- fileout "$heading trust_warn" "WARN" "$addtl_warning"
+ addtl_warning="(Your openssl <= 1.0.2 might be too unreliable to determine trust)"
+ fileout "${json_prefix}trust_warn" "WARN" "$addtl_warning"
fi
debugme outln
for bundle_fname in $ca_bundles; do
- certificate_file[i]=$(basename "$bundle_fname" | sed 's/\.pem//')
+ certificate_file[i]=$(basename ${bundle_fname//.pem})
if [[ ! -r $bundle_fname ]]; then
pr_litemagentaln "\"$bundle_fname\" cannot be found / not readable"
return 7
@@ -2696,20 +2713,20 @@ determine_trust() {
fi
i=$((i + 1))
done
- num_ca_bundles=$(($i - 1))
+ num_ca_bundles=$((i - 1))
debugme out " "
- # all stores ok
if $all_ok; then
- pr_litegreen "Ok "
- fileout "$heading trust" "OK" "All certificate trust checks passed. $addtl_warning"
- # at least one failed
+ # all stores ok
+ pr_litegreen "Ok "; pr_litemagenta "$addtl_warning"
+ fileout "${json_prefix}trust" "OK" "All certificate trust checks passed. $addtl_warning"
else
+ # at least one failed
pr_red "NOT ok"
if ! $some_ok; then
# all failed (we assume with the same issue), we're displaying the reason
out " "
verify_retcode_helper "${verify_retcode[2]}"
- fileout "$heading trust" "NOT OK" "All certificate trust checks failed: $(verify_retcode_helper "${verify_retcode[2]}"). $addtl_warning"
+ fileout "${json_prefix}trust" "NOT OK" "All certificate trust checks failed: $(verify_retcode_helper "${verify_retcode[2]}"). $addtl_warning"
else
# is one ok and the others not ==> display the culprit store
if $some_ok ; then
@@ -2728,20 +2745,19 @@ determine_trust() {
#pr_litered "$notok_was "
#outln "$code"
outln
- #lf + green ones
+ # lf + green ones
[[ "$DEBUG" -eq 0 ]] && out "$spaces"
pr_litegreen "OK: $ok_was"
fi
- fileout "$heading trust" "NOT OK" "Some certificate trust checks failed : OK : $ok_was NOT ok: $notok_was $addtl_warning"
+ fileout "${json_prefix}trust" "NOT OK" "Some certificate trust checks failed : OK : $ok_was NOT ok: $notok_was $addtl_warning"
fi
+ [[ -n "$addtl_warning" ]] && out "\n$spaces" && pr_litemagenta "$addtl_warning"
fi
outln
return 0
}
# not handled: Root CA supplied (contains anchor)
-# attention: 1.0.1 fails on mozilla
-
tls_time() {
local now difftime
@@ -2774,7 +2790,6 @@ tls_time() {
}
# core function determining whether handshake succeded or not
-#
sclient_connect_successful() {
[[ $1 -eq 0 ]] && return 0
[[ -n $(awk '/Master-Key: / { print $2 }' "$2") ]] && return 0
@@ -2800,7 +2815,7 @@ determine_tls_extensions() {
# alpn: echo | openssl s_client -connect google.com:443 -tlsextdebug -alpn h2-14 -servername google.com <-- suport needs to be checked b4 -- see also: ssl/t1_trce.c
$OPENSSL s_client $STARTTLS $BUGS $1 -showcerts -connect $NODEIP:$PORT $PROXY $SNI -$proto -tlsextdebug -nextprotoneg $alpn -status $ERRFILE >$TMPFILE
sclient_connect_successful $? $TMPFILE && success=0 && break
- done # this loop is needed for IIS/6
+ done # this loop is needed for IIS6 and others which have a handshake size limitations
if [[ $success -eq 7 ]]; then
# "-status" above doesn't work for GOST only servers, so we do another test without it and see whether that works then:
$OPENSSL s_client $STARTTLS $BUGS $1 -showcerts -connect $NODEIP:$PORT $PROXY $SNI -$proto -tlsextdebug >$ERRFILE >$TMPFILE
@@ -2814,7 +2829,13 @@ determine_tls_extensions() {
GOST_STATUS_PROBLEM=true
fi
fi
- TLS_EXTENSIONS=$(awk -F'"' '/TLS server extension / { printf "\""$2"\" " }' $TMPFILE)
+ #TLS_EXTENSIONS=$(awk -F'"' '/TLS server extension / { printf "\""$2"\" " }' $TMPFILE)
+ #
+ # this is not beautiful (grep+sed)
+ # but maybe we should just get the ids and do a private matching, according to
+ # https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml <-- ALPN is missing
+ TLS_EXTENSIONS=$(grep -a 'TLS server extension ' $TMPFILE | sed -e 's/TLS server extension //g' -e 's/\" (id=/\/#/g' -e 's/,.*$/,/g' -e 's/),$/\"/g')
+ TLS_EXTENSIONS=$(echo $TLS_EXTENSIONS) # into one line
# Place the server's certificate in $HOSTCERT and any intermediate
# certificates that were provided in $TEMPDIR/intermediatecerts.pem
@@ -2843,6 +2864,21 @@ determine_tls_extensions() {
return $success
}
+# arg1: path to certificate
+# returns CN
+get_cn_from_cert() {
+ local subject
+
+ # attention! openssl 1.0.2 doesn't properly handle online output from certifcates from trustwave.com/github.com
+ #FIXME: use -nameopt oid for robustness
+
+ # for e.g. russian sites -esc_msb,utf8 works in an UTF8 terminal -- any way to check platform indepedent?
+ # see x509(1ssl):
+ subject="$($OPENSSL x509 -in $1 -noout -subject -nameopt multiline,-align,sname,-esc_msb,utf8,-space_eq 2>>$ERRFILE)"
+ echo "$(awk -F'=' '/CN=/ { print $2 }' <<< "$subject")"
+ return $?
+}
+
certificate_info() {
local proto
@@ -2862,6 +2898,7 @@ certificate_info() {
local cnfinding
local cnok="OK"
local expfinding expok="OK"
+ local json_prefix="" # string to place at begging of JSON IDs when there is more than one certificate
local indent=""
if [[ $number_of_certificates -gt 1 ]]; then
@@ -2869,19 +2906,54 @@ certificate_info() {
indent=" "
out "$indent"
pr_headlineln "Server Certificate #$certificate_number"
+ json_prefix="Server Certificate #$certificate_number "
spaces=" "
else
spaces=" "
fi
- out "$indent"
- pr_bold " Server key size "
sig_algo=$($OPENSSL x509 -in $HOSTCERT -noout -text 2>>$ERRFILE | grep "Signature Algorithm" | sed 's/^.*Signature Algorithm: //' | sort -u )
key_algo=$($OPENSSL x509 -in $HOSTCERT -noout -text 2>>$ERRFILE | awk -F':' '/Public Key Algorithm:/ { print $2 }' | sort -u )
+ out "$indent" ; pr_bold " Signature Algorithm "
+ case $sig_algo in
+ sha1WithRSAEncryption)
+ pr_brownln "SHA1 with RSA"
+ fileout "${json_prefix}algorithm" "WARN" "Signature Algorithm: SHA1 with RSA (warning)"
+ ;;
+ sha256WithRSAEncryption)
+ pr_litegreenln "SHA256 with RSA"
+ fileout "${json_prefix}algorithm" "OK" "Signature Algorithm: SHA256 with RSA (OK)"
+ ;;
+ sha384WithRSAEncryption)
+ pr_litegreenln "SHA384 with RSA"
+ fileout "${json_prefix}algorithm" "OK" "Signature Algorithm: SHA384 with RSA (OK)"
+ ;;
+ sha512WithRSAEncryption)
+ pr_litegreenln "SHA512 with RSA"
+ fileout "${json_prefix}algorithm" "OK" "Signature Algorithm: SHA512 with RSA (OK)"
+ ;;
+ ecdsa-with-SHA256)
+ pr_litegreenln "ECDSA with SHA256"
+ fileout "${json_prefix}algorithm" "OK" "Signature Algorithm: ECDSA with SHA256 (OK)"
+ ;;
+ md5*)
+ pr_redln "MD5"
+ fileout "${json_prefix}algorithm" "NOT OK" "Signature Algorithm: MD5 (NOT ok)"
+ ;;
+ *)
+ out "$sig_algo ("
+ pr_litemagenta "Unknown"
+ outln ")"
+ fileout "${json_prefix}algorithm" "INFO" "Signature Algorithm: $sign_algo"
+ ;;
+ esac
+ # old, but interesting: https://blog.hboeck.de/archives/754-Playing-with-the-EFF-SSL-Observatory.html
+
+ out "$indent"; pr_bold " Server key size "
if [[ -z "$keysize" ]]; then
outln "(couldn't determine)"
- fileout "$heading key_size" "WARN" "Server keys size cannot be determined"
+ fileout "${json_prefix}key_size" "WARN" "Server keys size cannot be determined"
else
# https://tools.ietf.org/html/rfc4492, http://www.keylength.com/en/compare/
# http://infoscience.epfl.ch/record/164526/files/NPDF-22.pdf
@@ -2890,79 +2962,55 @@ certificate_info() {
if [[ $sig_algo =~ ecdsa ]] || [[ $key_algo =~ ecPublicKey ]]; then
if [[ "$keysize" -le 110 ]]; then # a guess
pr_red "$keysize"
- fileout "$heading key_size" "NOT OK" "Server keys $keysize EC bits (NOT ok)"
+ fileout "${json_prefix}key_size" "NOT OK" "Server keys $keysize EC bits (NOT ok)"
elif [[ "$keysize" -le 123 ]]; then # a guess
pr_litered "$keysize"
- fileout "$heading key_size" "NOT OK" "Server keys $keysize EC bits (NOT ok)"
+ fileout "${json_prefix}key_size" "NOT OK" "Server keys $keysize EC bits (NOT ok)"
elif [[ "$keysize" -le 163 ]]; then
pr_brown "$keysize"
- fileout "$heading key_size" "NOT OK" "Server keys $keysize EC bits (NOT ok)"
+ fileout "${json_prefix}key_size" "NOT OK" "Server keys $keysize EC bits (NOT ok)"
elif [[ "$keysize" -le 224 ]]; then
out "$keysize"
- fileout "$heading key_size" "INFO" "Server keys $keysize EC bits"
+ fileout "${json_prefix}key_size" "INFO" "Server keys $keysize EC bits"
elif [[ "$keysize" -le 533 ]]; then
pr_litegreen "$keysize"
- fileout "$heading key_size" "OK" "Server keys $keysize EC bits (OK)"
+ fileout "${json_prefix}key_size" "OK" "Server keys $keysize EC bits (OK)"
else
out "keysize: $keysize (not expected, FIXME)"
- fileout "$heading key_size" "WARN" "Server keys $keysize bits (not expected)"
+ fileout "${json_prefix}key_size" "WARN" "Server keys $keysize bits (not expected)"
fi
- else
+ outln " bit"
+ elif [[ $sig_algo = *RSA* ]]; then
if [[ "$keysize" -le 512 ]]; then
pr_red "$keysize"
- fileout "$heading key_size" "NOT OK" "Server keys $keysize bits (NOT ok)"
+ outln " bits"
+ fileout "${json_prefix}key_size" "NOT OK" "Server keys $keysize bits (NOT ok)"
elif [[ "$keysize" -le 768 ]]; then
pr_litered "$keysize"
- fileout "$heading key_size" "NOT OK" "Server keys $keysize bits (NOT ok)"
+ outln " bits"
+ fileout "${json_prefix}key_size" "NOT OK" "Server keys $keysize bits (NOT ok)"
elif [[ "$keysize" -le 1024 ]]; then
pr_brown "$keysize"
- fileout "$heading key_size" "NOT OK" "Server keys $keysize bits (NOT ok)"
+ outln " bits"
+ fileout "${json_prefix}key_size" "NOT OK" "Server keys $keysize bits (NOT ok)"
elif [[ "$keysize" -le 2048 ]]; then
- out "$keysize"
- fileout "$heading key_size" "INFO" "Server keys $keysize bits"
+ outln "$keysize bits"
+ fileout "${json_prefix}key_size" "INFO" "Server keys $keysize bits"
elif [[ "$keysize" -le 4096 ]]; then
pr_litegreen "$keysize"
- fileout "$heading key_size" "OK" "Server keys $keysize bits (OK)"
+ fileout "${json_prefix}key_size" "OK" "Server keys $keysize bits (OK)"
+ outln " bits"
else
- out "weird keysize: $keysize (compatibility problems)"
- fileout "$heading key_size" "WARN" "Server keys $keysize bits (Odd)"
+ pr_magenta "weird keysize: $keysize bits"; outln " (could cause compatibility problems)"
+ fileout "${json_prefix}key_size" "WARN" "Server keys $keysize bits (Odd)"
fi
+ else
+ out "$keysize bits ("
+ pr_litemagenta "can't tell whether $keysize bits is good or not"
+ outln ")"
+ fileout "${json_prefix}key_size" "WARN" "Server keys $keysize bits (unknown signature algorithm)"
fi
fi
- outln " bit"
-
- out "$indent" ; pr_bold " Signature Algorithm "
- case $sig_algo in
- sha1WithRSAEncryption)
- pr_brownln "SHA1 with RSA"
- fileout "$heading algorithm" "WARN" "Signature Algorithm: SHA1 with RSA (warning)"
- ;;
- sha256WithRSAEncryption)
- pr_litegreenln "SHA256 with RSA"
- fileout "$heading algorithm" "OK" "Signature Algorithm: SHA256 with RSA (OK)"
- ;;
- sha384WithRSAEncryption)
- pr_litegreenln "SHA384 with RSA"
- fileout "$heading algorithm" "OK" "Signature Algorithm: SHA384 with RSA (OK)"
- ;;
- sha512WithRSAEncryption)
- pr_litegreenln "SHA512 with RSA"
- fileout "$heading algorithm" "OK" "Signature Algorithm: SHA512 with RSA (OK)"
- ;;
- ecdsa-with-SHA256)
- pr_litegreenln "ECDSA with SHA256"
- fileout "$heading algorithm" "OK" "Signature Algorithm: ECDSA with SHA256 (OK)"
- ;;
- md5*)
- pr_redln "MD5"
- fileout "$heading algorithm" "NOT OK" "Signature Algorithm: MD5 (NOT ok)"
- ;;
- *)
- outln "$sig_algo"
- fileout "$heading algorithm" "INFO" "Signature Algorithm: $sign_algo"
- ;;
- esac
- # old, but interesting: https://blog.hboeck.de/archives/754-Playing-with-the-EFF-SSL-Observatory.html
out "$indent"; pr_bold " Fingerprint / Serial "
cert_fingerprint_sha1="$($OPENSSL x509 -noout -in $HOSTCERT -fingerprint -sha1 2>>$ERRFILE | sed 's/Fingerprint=//' | sed 's/://g')"
@@ -2970,12 +3018,12 @@ certificate_info() {
cert_fingerprint_sha2="$($OPENSSL x509 -noout -in $HOSTCERT -fingerprint -sha256 2>>$ERRFILE | sed 's/Fingerprint=//' | sed 's/://g' )"
outln "$cert_fingerprint_sha1 / $cert_fingerprint_serial"
outln "$spaces$cert_fingerprint_sha2"
- fileout "$heading fingerprint" "INFO" "Fingerprints / Serial: $cert_fingerprint_sha1 / $cert_fingerprint_serial, $cert_fingerprint_sha2"
+ fileout "${json_prefix}fingerprint" "INFO" "Fingerprints / Serial: $cert_fingerprint_sha1 / $cert_fingerprint_serial, $cert_fingerprint_sha2"
out "$indent"; pr_bold " Common Name (CN) "
cnfinding="Common Name (CN) : "
- if $OPENSSL x509 -in $HOSTCERT -noout -subject 2>>$ERRFILE | grep -wq CN; then
- cn=$($OPENSSL x509 -in $HOSTCERT -noout -subject 2>>$ERRFILE | sed 's/subject= //' | sed -e 's/^.*CN=//' -e 's/\/emailAdd.*//')
+ cn="$(get_cn_from_cert $HOSTCERT)"
+ if [[ -n "$cn" ]]; then
pr_dquoted "$cn"
cnfinding="$cn"
if echo -n "$cn" | grep -q '^*.' ; then
@@ -2992,26 +3040,25 @@ certificate_info() {
fi
fi
else
- cn="(no CN field in subject)"
- out "$cn"
+ cn="no CN field in subject"
+ pr_litemagenta "($cn)"
cnfinding="$cn"
cnok="INFO"
fi
- $OPENSSL s_client $STARTTLS $BUGS -cipher $cipher -connect $NODEIP:$PORT $PROXY $OPTIMAL_PROTO 2>>$ERRFILE $HOSTCERT.nosni
- cn_nosni=""
- if [[ -s $HOSTCERT.nosni ]]; then
- if $OPENSSL x509 -in $HOSTCERT.nosni -noout -subject 2>>$ERRFILE | grep -wq CN; then
- cn_nosni=$($OPENSSL x509 -in $HOSTCERT.nosni -noout -subject 2>>$ERRFILE | sed 's/subject= //' | sed -e 's/^.*CN=//' -e 's/\/emailAdd.*//')
- else
- cn_nosni="no CN field in subject"
- fi
- fi
-#FIXME: check for SSLv3/v2 and look wheher it goes to a different CN
+ # no cipher suites specified here. We just want the default vhost subject
+ $OPENSSL s_client $STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY $OPTIMAL_PROTO 2>>$ERRFILE $HOSTCERT.nosni
+ cn_nosni="$(get_cn_from_cert "$HOSTCERT.nosni")"
+ [[ -z "$cn_nosni" ]] && cn_nosni="no CN field in subject"
+
+#FIXME: check for SSLv3/v2 and look whether it goes to a different CN (probably not polite)
debugme out "\"$NODE\" | \"$cn\" | \"$cn_nosni\""
- if [[ $NODE == "$cn_nosni" ]]; then
- if [[ $SERVICE == "HTTP" ]] || $CLIENT_AUTH; then
+ if [[ "$cn_nosni" == "$cn" ]]; then
+ outln " (works w/o SNI)"
+ cnfinding+=" (works w/o SNI)"
+ elif [[ $NODE == "$cn_nosni" ]]; then
+ if [[ $SERVICE == "HTTP" ]] || $CLIENT_AUTH ; then
outln " (works w/o SNI)"
cnfinding+=" (works w/o SNI)"
else
@@ -3034,7 +3081,7 @@ certificate_info() {
fi
outln ")"
cnfinding+=")"
- elif [[ "$cn_nosni" == "*no CN field*" ]]; then
+ elif [[ "$cn_nosni" == *"no CN field"* ]]; then
outln ", (request w/o SNI: $cn_nosni)"
cnfinding+=", (request w/o SNI: $cn_nosni)"
else
@@ -3042,7 +3089,7 @@ certificate_info() {
cnfinding+=" (CN in response to request w/o SNI: \"$cn_nosni\")"
fi
fi
- fileout "$heading cn" "$cnok" "$cnfinding"
+ fileout "${json_prefix}cn" "$cnok" "$cnfinding"
sans=$($OPENSSL x509 -in $HOSTCERT -noout -text 2>>$ERRFILE | grep -A3 "Subject Alternative Name" | grep "DNS:" | \
sed -e 's/DNS://g' -e 's/ //g' -e 's/,/ /g' -e 's/othername://g')
@@ -3053,33 +3100,32 @@ certificate_info() {
pr_dquoted "$san"
out " "
done
- fileout "$heading san" "INFO" "subjectAltName (SAN) : $sans"
+ fileout "${json_prefix}san" "INFO" "subjectAltName (SAN) : $sans"
else
out "-- "
- fileout "$heading san" "INFO" "subjectAltName (SAN) : --"
+ fileout "${json_prefix}san" "INFO" "subjectAltName (SAN) : --"
fi
outln
out "$indent"; pr_bold " Issuer "
- issuer=$($OPENSSL x509 -in $HOSTCERT -noout -issuer 2>>$ERRFILE| sed -e 's/^.*CN=//g' -e 's/\/.*$//g')
- issuer_O=$($OPENSSL x509 -in $HOSTCERT -noout -issuer 2>>$ERRFILE | sed 's/^.*O=//g' | sed 's/\/.*$//g')
- if $OPENSSL x509 -in $HOSTCERT -noout -issuer 2>>$ERRFILE | grep -q 'C=' ; then
- issuer_C=$($OPENSSL x509 -in $HOSTCERT -noout -issuer 2>>$ERRFILE | sed 's/^.*C=//g' | sed 's/\/.*$//g')
+ #FIXME: oid would be better maybe (see above)
+ issuer="$($OPENSSL x509 -in $HOSTCERT -noout -issuer -nameopt multiline,-align,sname,-esc_msb,utf8,-space_eq 2>>$ERRFILE)"
+ issuer_CN="$(awk -F'=' '/CN=/ { print $2 }' <<< "$issuer")"
+ issuer_O="$(awk -F'=' '/O=/ { print $2 }' <<< "$issuer")"
+ issuer_C="$(awk -F'=' '/C=/ { print $2 }' <<< "$issuer")"
+
+ if [[ "$issuer_O" == "issuer=" ]] || [[ "$issuer_O" == "issuer= " ]] || [[ "$issuer_CN" == "$CN" ]]; then
+ pr_redln "self-signed (NOT ok)"
+ fileout "${json_prefix}issuer" "NOT OK" "Issuer: selfsigned (NOT ok)"
else
- issuer_C="" # CACert would have 'issuer= ' here otherwise
- fi
- if [[ "$issuer_O" == "issuer=" ]] || [[ "$issuer_O" == "issuer= " ]] || [[ "$issuer" == "$CN" ]]; then
- pr_redln "selfsigned (NOT ok)"
- fileout "$heading issuer" "NOT OK" "Issuer: selfsigned (NOT ok)"
- else
- pr_dquoted "$issuer"
+ pr_dquoted "$issuer_CN"
out " ("
pr_dquoted "$issuer_O"
if [[ -n "$issuer_C" ]]; then
out " from "
pr_dquoted "$issuer_C"
- fileout "$heading issuer" "INFO" "Issuer: \"$issuer\" ( \"$issuer_O\" from \"$issuer_C\")"
+ fileout "${json_prefix}issuer" "INFO" "Issuer: \"$issuer\" ( \"$issuer_O\" from \"$issuer_C\")"
else
- fileout "$heading issuer" "INFO" "Issuer: \"$issuer\" ( \"$issuer_O\" )"
+ fileout "${json_prefix}issuer" "INFO" "Issuer: \"$issuer\" ( \"$issuer_O\" )"
fi
outln ")"
fi
@@ -3096,10 +3142,10 @@ certificate_info() {
[[ 1.3.6.1.4.1.17326.10.8.12.1.2 == "$policy_oid" ]] || \
[[ 1.3.6.1.4.1.13177.10.1.3.10 == "$policy_oid" ]] ; then
out "yes "
- fileout "$heading ev" "OK" "Extended Validation (EV) (experimental) : yes"
+ fileout "${json_prefix}ev" "OK" "Extended Validation (EV) (experimental) : yes"
else
out "no "
- fileout "$heading ev" "INFO" "Extended Validation (EV) (experimental) : no"
+ fileout "${json_prefix}ev" "INFO" "Extended Validation (EV) (experimental) : no"
fi
debugme echo "($(newline_to_spaces "$policy_oid"))"
outln
@@ -3121,7 +3167,7 @@ certificate_info() {
fi
days2expire=$((days2expire / 3600 / 24 ))
- expire=$($OPENSSL x509 -in $HOSTCERT -checkend 0 2>>$ERRFILE)
+ expire=$($OPENSSL x509 -in $HOSTCERT -checkend 1 2>>$ERRFILE)
if ! echo $expire | grep -qw not; then
pr_red "expired!"
expfinding="expired!"
@@ -3147,72 +3193,75 @@ certificate_info() {
fi
fi
outln " ($startdate --> $enddate)"
- fileout "$heading expiration" "$expok" "Certificate Expiration : $expfinding ($startdate --> $enddate)"
+ fileout "${json_prefix}expiration" "$expok" "Certificate Expiration : $expfinding ($startdate --> $enddate)"
certificates_provided=1+$(grep -c "\-\-\-\-\-BEGIN CERTIFICATE\-\-\-\-\-" $TEMPDIR/intermediatecerts.pem)
out "$indent"; pr_bold " # of certificates provided"; outln " $certificates_provided"
- fileout "$heading certcount" "INFO" "# of certificates provided : $certificates_provided"
+ fileout "${json_prefix}certcount" "INFO" "# of certificates provided : $certificates_provided"
out "$indent"; pr_bold " Chain of trust"; out " (experim.) "
- determine_trust "$heading" #Also handles fileout
+ determine_trust "$json_prefix" # Also handles fileout
out "$indent"; pr_bold " Certificate Revocation List "
crl="$($OPENSSL x509 -in $HOSTCERT -noout -text 2>>$ERRFILE | grep -A 4 "CRL Distribution" | grep URI | sed 's/^.*URI://')"
if [[ -z "$crl" ]]; then
pr_literedln "--"
- fileout "$heading crl" "NOT OK" "No CRL provided (NOT ok)"
+ fileout "${json_prefix}crl" "NOT OK" "No CRL provided (NOT ok)"
elif grep -q http <<< "$crl"; then
if [[ $(count_lines "$crl") -eq 1 ]]; then
outln "$crl"
- fileout "$heading crl" "INFO" "Certificate Revocation List : $crl"
+ fileout "${json_prefix}crl" "INFO" "Certificate Revocation List : $crl"
else # more than one CRL
out_row_aligned "$crl" "$spaces"
- fileout "$heading crl" "INFO" "Certificate Revocation List : $crl"
+ fileout "${json_prefix}crl" "INFO" "Certificate Revocation List : $crl"
fi
else
pr_litemagentaln "no parsable output \"$crl\", pls report"
- fileout "$heading crl" "WARN" "Certificate Revocation List : no parsable output \"$crl\", pls report"
+ fileout "${json_prefix}crl" "WARN" "Certificate Revocation List : no parsable output \"$crl\", pls report"
fi
out "$indent"; pr_bold " OCSP URI "
ocsp_uri=$($OPENSSL x509 -in $HOSTCERT -noout -ocsp_uri 2>>$ERRFILE)
if [[ -z "$ocsp_uri" ]]; then
pr_literedln "--"
- fileout "$heading ocsp_uri" "NOT OK" "OCSP URI : -- (NOT ok)"
+ fileout "${json_prefix}ocsp_uri" "NOT OK" "OCSP URI : -- (NOT ok)"
else
outln "$ocsp_uri"
- fileout "$heading ocsp_uri" "INFO" "OCSP URI : $ocsp_uri"
+ fileout "${json_prefix}ocsp_uri" "INFO" "OCSP URI : $ocsp_uri"
fi
- out "$indent"; pr_bold " OCSP stapling "
+ out "$indent"; pr_bold " OCSP stapling "
if grep -a "OCSP response" <<<"$ocsp_response" | grep -q "no response sent" ; then
- outln " not offered"
- fileout "$heading ocsp_stapling" "INFO" "OCSP stapling : not offered"
+ pr_yellow "--"
+ fileout "${json_prefix}ocsp_stapling" "INFO" "OCSP stapling : not offered"
else
if grep -a "OCSP Response Status" <<<"$ocsp_response_status" | grep -q successful; then
- pr_litegreenln " offered"
- fileout "$heading ocsp_stapling" "OK" "OCSP stapling : offered"
+ pr_litegreen "offered"
+ fileout "${json_prefix}ocsp_stapling" "OK" "OCSP stapling : offered"
else
if $GOST_STATUS_PROBLEM; then
- outln " (GOST servers make problems here, sorry)"
- fileout "$heading ocsp_stapling" "OK" "OCSP stapling : (GOST servers make problems here, sorry)"
+ outln "(GOST servers make problems here, sorry)"
+ fileout "${json_prefix}ocsp_stapling" "OK" "OCSP stapling : (GOST servers make problems here, sorry)"
ret=0
else
- outln " not sure what's going on here, debug:"
- grep -aA 20 "OCSP response" <<<"$ocsp_response"
- fileout "$heading ocsp_stapling" "OK" "OCSP stapling : not sure what's going on here, debug: grep -aA 20 "OCSP response" <<<"$ocsp_response""
+ out "(response status unknown)"
+ fileout "${json_prefix}ocsp_stapling" "OK" "OCSP stapling : not sure what's going on here, debug: grep -aA 20 "OCSP response" <<<"$ocsp_response""
+ debugme grep -a -A20 -B2 "OCSP response" <<<"$ocsp_response"
ret=2
fi
fi
fi
- outln
+ outln "\n"
return $ret
}
# FIXME: revoked, see checkcert.sh
# FIXME: Trust (only CN)
+
+
+
run_server_defaults() {
local ciph match_found newhostcert
local sessticket_str=""
@@ -3304,7 +3353,7 @@ run_server_defaults() {
pr_headlineln " Testing server defaults (Server Hello) "
outln
- pr_bold " TLS server extensions (std) "
+ pr_bold " TLS extensions (standard) "
if [[ -z "$all_tls_extensions" ]]; then
outln "(none)"
fileout "tls_extensions" "INFO" "TLS server extensions (std): (none)"
@@ -3369,7 +3418,7 @@ run_pfs() {
nr_supported_ciphers=$(count_ciphers $(actually_supported_ciphers $pfs_cipher_list))
if [[ "$nr_supported_ciphers" -le "$CLIENT_MIN_PFS" ]]; then
outln
- local_problem "You only have $nr_supported_ciphers PFS ciphers on the client side "
+ local_problem_ln "You only have $nr_supported_ciphers PFS ciphers on the client side "
fileout "pfs" "WARN" "(Perfect) Forward Secrecy tests: Skipped. You only have $nr_supported_ciphers PFS ciphers on the client site. ($CLIENT_MIN_PFS are required)"
return 1
fi
@@ -3482,7 +3531,7 @@ http2_pre(){
return 1
fi
if ! $HAS_ALPN; then
- local_problem "$OPENSSL doesn't support HTTP2/ALPN";
+ local_problem_ln "$OPENSSL doesn't support HTTP2/ALPN";
fileout "https_alpn" "WARN" "HTTP2/ALPN : HTTP/2 was not tested as $OPENSSL does not support it"
return 7
fi
@@ -4424,10 +4473,6 @@ run_ccs_injection(){
return $ret
}
-local_problem() {
- pr_litemagentaln "Local problem: $1"
-}
-
run_renego() {
# no SNI here. Not needed as there won't be two different SSL stacks for one IP
local legacycmd=""
@@ -4469,7 +4514,7 @@ run_renego() {
0.9.8*) # we need this for Mac OSX unfortunately
case "$OSSL_VER_APPENDIX" in
[a-l])
- local_problem "$OPENSSL cannot test this secure renegotiation vulnerability"
+ local_problem_ln "$OPENSSL cannot test this secure renegotiation vulnerability"
fileout "sec_client_renego" "WARN" "Secure Client-Initiated Renegotiation : $OPENSSL cannot test this secure renegotiation vulnerability"
return 3
;;
@@ -4540,7 +4585,7 @@ run_crime() {
# first we need to test whether OpenSSL binary has zlib support
$OPENSSL zlib -e -a -in /dev/stdin &>/dev/stdout &1 | grep -qw nextprotoneg
+# $OPENSSL s_client -help 2>&1 | grep -qw nextprotoneg
# if [[ $? -eq 0 ]]; then
# $OPENSSL s_client -host $NODE -port $PORT -nextprotoneg $NPN_PROTOs $SNI /dev/null >$TMPFILE
# if [[ $? -eq 0 ]]; then
@@ -4618,7 +4663,7 @@ run_breach() {
local url
local spaces=" "
local disclaimer=""
- local when_makesense="Can be ignored for static pages or if no secrets in the page"
+ local when_makesense=" Can be ignored for static pages or if no secrets in the page"
[[ $SERVICE != "HTTP" ]] && return 7
@@ -4716,8 +4761,8 @@ run_tls_fallback_scsv() {
# the countermeasure to protect against protocol downgrade attacks.
# First check we have support for TLS_FALLBACK_SCSV in our local OpenSSL
- if ! $OPENSSL s_client -h 2>&1 | grep -q "\-fallback_scsv"; then
- local_problem "$OPENSSL lacks TLS_FALLBACK_SCSV support"
+ if ! $OPENSSL s_client -help 2>&1 | grep -q "\-fallback_scsv"; then
+ local_problem_ln "$OPENSSL lacks TLS_FALLBACK_SCSV support"
return 4
fi
#TODO: this need some tuning: a) if one protocol is supported only it has practcally no value (theoretical it's interesting though)
@@ -4784,7 +4829,7 @@ run_freak() {
case $nr_supported_ciphers in
0)
- local_problem "$OPENSSL doesn't have any EXPORT RSA ciphers configured"
+ local_problem_ln "$OPENSSL doesn't have any EXPORT RSA ciphers configured"
fileout "freak" "WARN" "FREAK (CVE-2015-0204) : Not tested. $OPENSSL doesn't have any EXPORT RSA ciphers configured"
return 7
;;
@@ -4830,7 +4875,7 @@ run_logjam() {
case $nr_supported_ciphers in
0)
- local_problem "$OPENSSL doesn't have any DHE EXPORT ciphers configured"
+ local_problem_ln "$OPENSSL doesn't have any DHE EXPORT ciphers configured"
fileout "logjam" "WARN" "LOGJAM (CVE-2015-4000) : Not tested. $OPENSSL doesn't have any DHE EXPORT ciphers configured"
return 3
;;
@@ -4891,12 +4936,11 @@ run_beast(){
outln
fi
pr_bold " BEAST"; out " (CVE-2011-3389) "
- "$WIDE" && outln
# output in wide mode if cipher doesn't exist is not ok
>$ERRFILE
- # first determine whether it's mitogated by higher protocols
+ # first determine whether it's mitigated by higher protocols
for proto in tls1_1 tls1_2; do
$OPENSSL s_client -state -"$proto" $STARTTLS $BUGS -connect $NODEIP:$PORT $PROXY $SNI 2>>$ERRFILE >$TMPFILE $TMPFILE 2>>$ERRFILE $TMPFILE 2>>$ERRFILE >$ERRFILE) # -V doesn't work with openssl < 1.0
@@ -4955,25 +5001,27 @@ run_beast(){
fi
done
- if [[ -n "$detected_cbc_ciphers" ]]; then
- fileout "cbc_$proto" "NOT OK" "BEAST (CVE-2011-3389) : CBC ciphers for $(toupper $proto): $detected_cbc_ciphers"
- if ! "$WIDE"; then
+ if ! "$WIDE"; then
+ if [[ -n "$detected_cbc_ciphers" ]]; then
detected_cbc_ciphers=$(echo "$detected_cbc_ciphers" | sed -e "s/ /\\${cr} ${spaces}/9" -e "s/ /\\${cr} ${spaces}/6" -e "s/ /\\${cr} ${spaces}/3")
+ fileout "cbc_$proto" "NOT OK" "BEAST (CVE-2011-3389) : CBC ciphers for $(toupper $proto): $detected_cbc_ciphers"
! "$first" && out "$spaces"
out "$(toupper $proto):"
[[ -n "$higher_proto_supported" ]] && \
pr_yellowln "$detected_cbc_ciphers" || \
pr_brownln "$detected_cbc_ciphers"
- detected_cbc_ciphers="" # empty for next round
+ detected_cbc_ciphers="" # empty for next round
+ first=false
+ else
+ [[ $proto == "tls1" ]] && ! $first && echo -n "$spaces "
+ pr_litegreenln "no CBC ciphers for $(toupper $proto) (OK)"
first=false
fi
else
- fileout "cbc_$proto" "OK" "BEAST (CVE-2011-3389) : No CBC ciphers for $(toupper $proto) (OK)"
- if ! "$WIDE"; then
- [[ $proto == "tls1" ]] && ! $first && echo -n "$spaces "
- first=false
+ if ! "$vuln_beast" ; then
+ pr_litegreenln " no CBC ciphers for $(toupper $proto) (OK)"
+ fileout "cbc_$proto" "OK" "BEAST (CVE-2011-3389) : No CBC ciphers for $(toupper $proto) (OK)"
fi
- pr_litegreenln "no CBC ciphers for $(toupper $proto) (OK)"
fi
done # for proto in ssl3 tls1
@@ -4981,11 +5029,11 @@ run_beast(){
if [[ -n "$higher_proto_supported" ]]; then
if "$WIDE"; then
outln
- # BOT ok seems too harsh for me if we have TLS >1.0
+ # NOT ok seems too harsh for me if we have TLS >1.0
pr_yellow "VULNERABLE"
outln " -- but also supports higher protocols (possible mitigation):$higher_proto_supported"
else
- out "${spaces}"
+ out "$spaces"
pr_yellow "VULNERABLE"
outln " -- but also supports higher protocols (possible mitigation):$higher_proto_supported"
fi
@@ -4994,14 +5042,14 @@ run_beast(){
if "$WIDE"; then
outln
else
- out "${spaces}"
+ out "$spaces"
fi
pr_brown "VULNERABLE (NOT ok)"
outln " -- and no higher protocols as mitigation supported"
fileout "beast" "NOT OK" "BEAST (CVE-2011-3389) : VULNERABLE -- and no higher protocols as mitigation supported"
fi
fi
- $first && pr_litegreenln "no CBC ciphers found for any protocol (OK)"
+ "$first" && ! "$vuln_beast" && pr_litegreenln "no CBC ciphers found for any protocol (OK)"
tmpfile_handle $FUNCNAME.txt
return 0
@@ -5214,10 +5262,10 @@ find_openssl_binary() {
$OPENSSL s_client -ssl3 2>&1 | grep -aq "unknown option" || \
HAS_SSL3=true && \
HAS_SSL3=false
- $OPENSSL s_client help 2>&1 | grep -qw '\-alpn' && \
+ $OPENSSL s_client -help 2>&1 | grep -qw '\-alpn' && \
HAS_ALPN=true || \
HAS_ALPN=false
- $OPENSSL s_client help 2>&1 | grep -qw '\-nextprotoneg' && \
+ $OPENSSL s_client -help 2>&1 | grep -qw '\-nextprotoneg' && \
HAS_SPDY=true || \
HAS_SPDY=false
@@ -5245,10 +5293,6 @@ openssl_age() {
esac
ignore_no_or_lame " Type \"yes\" to accept some false negatives or positives "
fi
- if [[ $OSSL_VER_MAJOR.$OSSL_VER_MINOR == "1.1.0" ]]; then
- pr_magentaln "$PROG_NAME doesn't work yet with OpenSSL 1.1.0!"
- ignore_no_or_lame "Type \"yes\" to accept weird output, false negatives and positives "
- fi
outln
}
@@ -5852,7 +5896,7 @@ get_mx_record() {
#
check_proxy() {
if [[ -n "$PROXY" ]]; then
- if ! $OPENSSL s_client help 2>&1 | grep -qw proxy; then
+ if ! $OPENSSL s_client -help 2>&1 | grep -qw proxy; then
fatal "Your $OPENSSL is too old to support the \"--proxy\" option" -1
fi
PROXYNODE=${PROXY%:*}
@@ -6716,4 +6760,4 @@ fi
exit $?
-# $Id: testssl.sh,v 1.456 2016/02/01 16:33:58 dirkw Exp $
+# $Id: testssl.sh,v 1.464 2016/02/07 18:13:58 dirkw Exp $