Index: configure ================================================================== --- configure +++ configure @@ -2810,14 +2810,20 @@ `ls -d /usr/local/lib 2>/dev/null` \ `ls -d /usr/contrib/lib 2>/dev/null` \ `ls -d /usr/pkg/lib 2>/dev/null` \ `ls -d /usr/lib 2>/dev/null` \ `ls -d /usr/lib64 2>/dev/null` \ + `ls -d /usr/lib/tcl9.0 2>/dev/null` \ + `ls -d /usr/lib/tcl8.7 2>/dev/null` \ `ls -d /usr/lib/tcl8.6 2>/dev/null` \ `ls -d /usr/lib/tcl8.5 2>/dev/null` \ + `ls -d /usr/local/lib/tcl9.0 2>/dev/null` \ + `ls -d /usr/local/lib/tcl8.7 2>/dev/null` \ `ls -d /usr/local/lib/tcl8.6 2>/dev/null` \ `ls -d /usr/local/lib/tcl8.5 2>/dev/null` \ + `ls -d /usr/local/lib/tcl/tcl9.0 2>/dev/null` \ + `ls -d /usr/local/lib/tcl/tcl8.7 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl8.6 2>/dev/null` \ `ls -d /usr/local/lib/tcl/tcl8.5 2>/dev/null` \ ; do if test -f "$i/tclConfig.sh" ; then ac_cv_c_tclconfig="`(cd $i; pwd)`" Index: tests/all.tcl ================================================================== --- tests/all.tcl +++ tests/all.tcl @@ -18,11 +18,11 @@ namespace import ::tcltest::* } # Get common functions if {[file exists [file join $path common.tcl]]} { - source [file join $path common.tcl] + source -encoding utf-8 [file join $path common.tcl] } set ::tcltest::testSingleFile false set ::tcltest::testsDirectory [file dir [info script]] @@ -31,23 +31,23 @@ catch {::tcltest::normalizePath ::tcltest::testsDirectory} # # Run all tests in current and any sub directories with an all.tcl file. # -set exitCode 0 +set ::exitCode 0 if {[package vsatisfies [package require tcltest] 2.5-]} { if {[::tcltest::runAllTests] == 1} { - set exitCode 1 + set ::exitCode 1 } } else { # Hook to determine if any of the tests failed. Then we can exit with the # proper exit code: 0=all passed, 1=one or more failed proc tcltest::cleanupTestsHook {} { variable numTests - set exitCode [expr {$numTests(Total) == 0 || $numTests(Failed) > 0}] + set ::exitCode [expr {$numTests(Total) == 0 || $numTests(Failed) > 0}] } ::tcltest::runAllTests } # Exit code: 0=all passed, 1=one or more failed -exit $exitCode +exit $::exitCode Index: tests/badssl.csv ================================================================== --- tests/badssl.csv +++ tests/badssl.csv @@ -8,11 +8,11 @@ command,"proc badssl {url} {set port 443;lassign [split $url "":""] url port;if {$port eq """"} {set port 443};set cmd [list tls::socket -autoservername 1 -require 1];if {[info exists ::env(SSL_CERT_FILE)]} {lappend cmd -cafile $::env(SSL_CERT_FILE)};lappend cmd $url $port;set ch [eval $cmd];if {[catch {tls::handshake $ch} err]} {close $ch;return -code error $err} else {close $ch}}",,,,,,,,, ,,,,,,,,,, command,# BadSSL.com Tests,,,,,,,,, BadSSL,1000-sans,,,badssl 1000-sans.badssl.com,,,"handshake failed: certificate verify failed due to ""certificate has expired""",,,1 BadSSL,10000-sans,,,badssl 10000-sans.badssl.com,,,handshake failed: excessive message size,,,1 -BadSSL,3des,,,badssl 3des.badssl.com,,,handshake failed: sslv3 alert handshake failure,,,1 +BadSSL,3des,,,badssl 3des.badssl.com,,glob,handshake failed: * alert handshake failure,,,1 BadSSL,captive-portal,old_api,,badssl captive-portal.badssl.com,,,"handshake failed: certificate verify failed due to ""Hostname mismatch""",,,1 BadSSL,captive-portal,new_api,,badssl captive-portal.badssl.com,,,"handshake failed: certificate verify failed due to ""hostname mismatch""",,,1 BadSSL,cbc,,,badssl cbc.badssl.com,,,,,, BadSSL,client-cert-missing,,,badssl client-cert-missing.badssl.com,,,,,, BadSSL,client,,,badssl client.badssl.com,,,,,, @@ -19,11 +19,12 @@ BadSSL,dh-composite,old_api,,badssl dh-composite.badssl.com,,,,,, BadSSL,dh-composite,new_api,,badssl dh-composite.badssl.com,,,handshake failed: dh key too small,,,1 BadSSL,dh-small-subgroup,,,badssl dh-small-subgroup.badssl.com,,,,,, BadSSL,dh480,old_api,,badssl dh480.badssl.com,,,handshake failed: dh key too small,,,1 BadSSL,dh480,new_api,,badssl dh480.badssl.com,,,handshake failed: modulus too small,,,1 -BadSSL,dh512,,,badssl dh512.badssl.com,,,handshake failed: dh key too small,,,1 +BadSSL,dh512,old_api,,badssl dh512.badssl.com,,,handshake failed: dh key too small,,,1 +BadSSL,dh512,mac,,badssl dh512.badssl.com,,,handshake failed: unknown security bits,,,1 BadSSL,dh1024,old_api,,badssl dh1024.badssl.com,,,,,, BadSSL,dh1024,new_api,,badssl dh1024.badssl.com,,,handshake failed: dh key too small,,,1 BadSSL,dh2048,,,badssl dh2048.badssl.com,,,,,, BadSSL,dsdtestprovider,,,badssl dsdtestprovider.badssl.com,,,"handshake failed: certificate verify failed due to ""unable to get local issuer certificate""",,,1 BadSSL,ecc256,,,badssl ecc256.badssl.com,,,,,, @@ -39,16 +40,16 @@ BadSSL,longextendedsubdomainnamewithoutdashesinordertotestwordwrapping,,,badssl longextendedsubdomainnamewithoutdashesinordertotestwordwrapping.badssl.com,,,,,, BadSSL,mitm-software,,,badssl mitm-software.badssl.com,,,"handshake failed: certificate verify failed due to ""unable to get local issuer certificate""",,,1 BadSSL,no-common-name,,,badssl no-common-name.badssl.com,,,"handshake failed: certificate verify failed due to ""certificate has expired""",,,1 BadSSL,no-sct,,,badssl no-sct.badssl.com,,,"handshake failed: certificate verify failed due to ""unable to get local issuer certificate""",,,1 BadSSL,no-subject,,,badssl no-subject.badssl.com,,,"handshake failed: certificate verify failed due to ""certificate has expired""",,,1 -BadSSL,null,,,badssl null.badssl.com,,,handshake failed: sslv3 alert handshake failure,,,1 +BadSSL,null,,,badssl null.badssl.com,,glob,handshake failed: * alert handshake failure,,,1 BadSSL,pinning-test,,,badssl pinning-test.badssl.com,,,,,, BadSSL,preact-cli,,,badssl preact-cli.badssl.com,,,"handshake failed: certificate verify failed due to ""unable to get local issuer certificate""",,,1 BadSSL,preloaded-hsts,,,badssl preloaded-hsts.badssl.com,,,,,, -BadSSL,rc4-md5,,,badssl rc4-md5.badssl.com,,,handshake failed: sslv3 alert handshake failure,,,1 -BadSSL,rc4,,,badssl rc4.badssl.com,,,handshake failed: sslv3 alert handshake failure,,,1 +BadSSL,rc4-md5,,,badssl rc4-md5.badssl.com,,glob,handshake failed: * alert handshake failure,,,1 +BadSSL,rc4,,,badssl rc4.badssl.com,,glob,handshake failed: * alert handshake failure,,,1 BadSSL,revoked,,,badssl revoked.badssl.com,,,"handshake failed: certificate verify failed due to ""certificate has expired""",,,1 BadSSL,rsa2048,,,badssl rsa2048.badssl.com,,,,,, BadSSL,rsa4096,,,badssl rsa4096.badssl.com,,,,,, BadSSL,rsa8192,,,badssl rsa8192.badssl.com,,,,,, BadSSL,self-signed,old_api,,badssl self-signed.badssl.com,,,"handshake failed: certificate verify failed due to ""self signed certificate""",,,1 Index: tests/badssl.test ================================================================== --- tests/badssl.test +++ tests/badssl.test @@ -27,11 +27,11 @@ badssl 10000-sans.badssl.com } -result {handshake failed: excessive message size} -returnCodes {1} test BadSSL-1.3 {3des} -body { badssl 3des.badssl.com - } -result {handshake failed: ssl/tls alert handshake failure} -returnCodes {1} + } -match {glob} -result {handshake failed: * alert handshake failure} -returnCodes {1} test BadSSL-1.4 {captive-portal} -constraints {old_api} -body { badssl captive-portal.badssl.com } -result {handshake failed: certificate verify failed due to "Hostname mismatch"} -returnCodes {1} @@ -69,228 +69,232 @@ test BadSSL-1.13 {dh480} -constraints {new_api} -body { badssl dh480.badssl.com } -result {handshake failed: modulus too small} -returnCodes {1} -test BadSSL-1.14 {dh512} -body { +test BadSSL-1.14 {dh512} -constraints {old_api} -body { badssl dh512.badssl.com } -result {handshake failed: dh key too small} -returnCodes {1} -test BadSSL-1.15 {dh1024} -constraints {old_api} -body { +test BadSSL-1.15 {dh512} -constraints {mac} -body { + badssl dh512.badssl.com + } -result {handshake failed: unknown security bits} -returnCodes {1} + +test BadSSL-1.16 {dh1024} -constraints {old_api} -body { badssl dh1024.badssl.com } -test BadSSL-1.16 {dh1024} -constraints {new_api} -body { +test BadSSL-1.17 {dh1024} -constraints {new_api} -body { badssl dh1024.badssl.com } -result {handshake failed: dh key too small} -returnCodes {1} -test BadSSL-1.17 {dh2048} -body { +test BadSSL-1.18 {dh2048} -body { badssl dh2048.badssl.com } -test BadSSL-1.18 {dsdtestprovider} -body { +test BadSSL-1.19 {dsdtestprovider} -body { badssl dsdtestprovider.badssl.com } -result {handshake failed: certificate verify failed due to "unable to get local issuer certificate"} -returnCodes {1} -test BadSSL-1.19 {ecc256} -body { +test BadSSL-1.20 {ecc256} -body { badssl ecc256.badssl.com } -test BadSSL-1.20 {ecc384} -body { +test BadSSL-1.21 {ecc384} -body { badssl ecc384.badssl.com } -test BadSSL-1.21 {edellroot} -body { +test BadSSL-1.22 {edellroot} -body { badssl edellroot.badssl.com } -result {handshake failed: certificate verify failed due to "unable to get local issuer certificate"} -returnCodes {1} -test BadSSL-1.22 {expired} -body { +test BadSSL-1.23 {expired} -body { badssl expired.badssl.com } -result {handshake failed: certificate verify failed due to "certificate has expired"} -returnCodes {1} -test BadSSL-1.23 {extended-validation} -body { +test BadSSL-1.24 {extended-validation} -body { badssl extended-validation.badssl.com } -result {handshake failed: certificate verify failed due to "certificate has expired"} -returnCodes {1} -test BadSSL-1.24 {hsts} -body { +test BadSSL-1.25 {hsts} -body { badssl hsts.badssl.com } -test BadSSL-1.25 {https-everywhere} -body { +test BadSSL-1.26 {https-everywhere} -body { badssl https-everywhere.badssl.com } -test BadSSL-1.26 {incomplete-chain} -body { +test BadSSL-1.27 {incomplete-chain} -body { badssl incomplete-chain.badssl.com } -result {handshake failed: certificate verify failed due to "unable to get local issuer certificate"} -returnCodes {1} -test BadSSL-1.27 {invalid-expected-sct} -body { +test BadSSL-1.28 {invalid-expected-sct} -body { badssl invalid-expected-sct.badssl.com } -result {handshake failed: certificate verify failed due to "unable to get local issuer certificate"} -returnCodes {1} -test BadSSL-1.28 {long-extended-subdomain-name-containing-many-letters-and-dashes} -body { +test BadSSL-1.29 {long-extended-subdomain-name-containing-many-letters-and-dashes} -body { badssl long-extended-subdomain-name-containing-many-letters-and-dashes.badssl.com } -test BadSSL-1.29 {longextendedsubdomainnamewithoutdashesinordertotestwordwrapping} -body { +test BadSSL-1.30 {longextendedsubdomainnamewithoutdashesinordertotestwordwrapping} -body { badssl longextendedsubdomainnamewithoutdashesinordertotestwordwrapping.badssl.com } -test BadSSL-1.30 {mitm-software} -body { +test BadSSL-1.31 {mitm-software} -body { badssl mitm-software.badssl.com } -result {handshake failed: certificate verify failed due to "unable to get local issuer certificate"} -returnCodes {1} -test BadSSL-1.31 {no-common-name} -body { +test BadSSL-1.32 {no-common-name} -body { badssl no-common-name.badssl.com } -result {handshake failed: certificate verify failed due to "certificate has expired"} -returnCodes {1} -test BadSSL-1.32 {no-sct} -body { +test BadSSL-1.33 {no-sct} -body { badssl no-sct.badssl.com } -result {handshake failed: certificate verify failed due to "unable to get local issuer certificate"} -returnCodes {1} -test BadSSL-1.33 {no-subject} -body { +test BadSSL-1.34 {no-subject} -body { badssl no-subject.badssl.com } -result {handshake failed: certificate verify failed due to "certificate has expired"} -returnCodes {1} -test BadSSL-1.34 {null} -body { +test BadSSL-1.35 {null} -body { badssl null.badssl.com - } -result {handshake failed: ssl/tls alert handshake failure} -returnCodes {1} + } -match {glob} -result {handshake failed: * alert handshake failure} -returnCodes {1} -test BadSSL-1.35 {pinning-test} -body { +test BadSSL-1.36 {pinning-test} -body { badssl pinning-test.badssl.com } -test BadSSL-1.36 {preact-cli} -body { +test BadSSL-1.37 {preact-cli} -body { badssl preact-cli.badssl.com } -result {handshake failed: certificate verify failed due to "unable to get local issuer certificate"} -returnCodes {1} -test BadSSL-1.37 {preloaded-hsts} -body { +test BadSSL-1.38 {preloaded-hsts} -body { badssl preloaded-hsts.badssl.com } -test BadSSL-1.38 {rc4-md5} -body { +test BadSSL-1.39 {rc4-md5} -body { badssl rc4-md5.badssl.com - } -result {handshake failed: ssl/tls alert handshake failure} -returnCodes {1} + } -match {glob} -result {handshake failed: * alert handshake failure} -returnCodes {1} -test BadSSL-1.39 {rc4} -body { +test BadSSL-1.40 {rc4} -body { badssl rc4.badssl.com - } -result {handshake failed: ssl/tls alert handshake failure} -returnCodes {1} + } -match {glob} -result {handshake failed: * alert handshake failure} -returnCodes {1} -test BadSSL-1.40 {revoked} -body { +test BadSSL-1.41 {revoked} -body { badssl revoked.badssl.com } -result {handshake failed: certificate verify failed due to "certificate has expired"} -returnCodes {1} -test BadSSL-1.41 {rsa2048} -body { +test BadSSL-1.42 {rsa2048} -body { badssl rsa2048.badssl.com } -test BadSSL-1.42 {rsa4096} -body { +test BadSSL-1.43 {rsa4096} -body { badssl rsa4096.badssl.com } -test BadSSL-1.43 {rsa8192} -body { +test BadSSL-1.44 {rsa8192} -body { badssl rsa8192.badssl.com } -test BadSSL-1.44 {self-signed} -constraints {old_api} -body { +test BadSSL-1.45 {self-signed} -constraints {old_api} -body { badssl self-signed.badssl.com } -result {handshake failed: certificate verify failed due to "self signed certificate"} -returnCodes {1} -test BadSSL-1.45 {self-signed} -constraints {new_api} -body { +test BadSSL-1.46 {self-signed} -constraints {new_api} -body { badssl self-signed.badssl.com } -result {handshake failed: certificate verify failed due to "self-signed certificate"} -returnCodes {1} -test BadSSL-1.46 {sha1-2016} -body { +test BadSSL-1.47 {sha1-2016} -body { badssl sha1-2016.badssl.com } -result {handshake failed: certificate verify failed due to "unable to get local issuer certificate"} -returnCodes {1} -test BadSSL-1.47 {sha1-2017} -constraints {old_api} -body { +test BadSSL-1.48 {sha1-2017} -constraints {old_api} -body { badssl sha1-2017.badssl.com } -result {handshake failed: certificate verify failed due to "certificate has expired"} -returnCodes {1} -test BadSSL-1.48 {sha1-2017} -constraints {new_api} -body { +test BadSSL-1.49 {sha1-2017} -constraints {new_api} -body { badssl sha1-2017.badssl.com } -result {handshake failed: certificate verify failed due to "CA signature digest algorithm too weak"} -returnCodes {1} -test BadSSL-1.49 {sha1-intermediate} -body { +test BadSSL-1.50 {sha1-intermediate} -body { badssl sha1-intermediate.badssl.com } -result {handshake failed: certificate verify failed due to "unable to get local issuer certificate"} -returnCodes {1} -test BadSSL-1.50 {sha256} -body { +test BadSSL-1.51 {sha256} -body { badssl sha256.badssl.com } -test BadSSL-1.51 {sha384} -body { +test BadSSL-1.52 {sha384} -body { badssl sha384.badssl.com } -result {handshake failed: certificate verify failed due to "certificate has expired"} -returnCodes {1} -test BadSSL-1.52 {sha512} -body { +test BadSSL-1.53 {sha512} -body { badssl sha512.badssl.com } -result {handshake failed: certificate verify failed due to "certificate has expired"} -returnCodes {1} -test BadSSL-1.53 {static-rsa} -body { +test BadSSL-1.54 {static-rsa} -body { badssl static-rsa.badssl.com } -test BadSSL-1.54 {subdomain.preloaded-hsts} -constraints {old_api} -body { - badssl subdomain.preloaded-hsts.badssl.com - } -result {handshake failed: certificate verify failed due to "Hostname mismatch"} -returnCodes {1} - -test BadSSL-1.55 {subdomain.preloaded-hsts} -constraints {new_api} -body { - badssl subdomain.preloaded-hsts.badssl.com - } -result {handshake failed: certificate verify failed due to "hostname mismatch"} -returnCodes {1} - -test BadSSL-1.56 {superfish} -body { - badssl superfish.badssl.com - } -result {handshake failed: certificate verify failed due to "unable to get local issuer certificate"} -returnCodes {1} - -test BadSSL-1.57 {tls-v1-0:1010} -constraints {tls1 old_api} -body { - badssl tls-v1-0.badssl.com:1010 - } - -test BadSSL-1.58 {tls-v1-0:1010} -constraints {tls1 new_api} -body { - badssl tls-v1-0.badssl.com:1010 - } -result {handshake failed: unsupported protocol} -returnCodes {1} - -test BadSSL-1.59 {tls-v1-1:1011} -constraints {tls1.1 old_api} -body { - badssl tls-v1-1.badssl.com:1011 - } - -test BadSSL-1.60 {tls-v1-1:1011} -constraints {tls1.1 new_api} -body { - badssl tls-v1-1.badssl.com:1011 - } -result {handshake failed: unsupported protocol} -returnCodes {1} - -test BadSSL-1.61 {tls-v1-2:1012} -constraints {tls1.2} -body { - badssl tls-v1-2.badssl.com:1012 - } - -test BadSSL-1.62 {untrusted-root} -constraints {old_api} -body { - badssl untrusted-root.badssl.com - } -result {handshake failed: certificate verify failed due to "self signed certificate in certificate chain"} -returnCodes {1} - -test BadSSL-1.63 {untrusted-root} -constraints {new_api} -body { - badssl untrusted-root.badssl.com - } -result {handshake failed: certificate verify failed due to "self-signed certificate in certificate chain"} -returnCodes {1} - -test BadSSL-1.64 {upgrade} -body { - badssl upgrade.badssl.com - } - -test BadSSL-1.65 {webpack-dev-server} -body { - badssl webpack-dev-server.badssl.com - } -result {handshake failed: certificate verify failed due to "unable to get local issuer certificate"} -returnCodes {1} - -test BadSSL-1.66 {wrong.host} -constraints {old_api} -body { - badssl wrong.host.badssl.com - } -result {handshake failed: certificate verify failed due to "Hostname mismatch"} -returnCodes {1} - -test BadSSL-1.67 {wrong.host} -constraints {new_api} -body { - badssl wrong.host.badssl.com - } -result {handshake failed: certificate verify failed due to "hostname mismatch"} -returnCodes {1} - -test BadSSL-1.68 {mozilla-modern} -body { +test BadSSL-1.55 {subdomain.preloaded-hsts} -constraints {old_api} -body { + badssl subdomain.preloaded-hsts.badssl.com + } -result {handshake failed: certificate verify failed due to "Hostname mismatch"} -returnCodes {1} + +test BadSSL-1.56 {subdomain.preloaded-hsts} -constraints {new_api} -body { + badssl subdomain.preloaded-hsts.badssl.com + } -result {handshake failed: certificate verify failed due to "hostname mismatch"} -returnCodes {1} + +test BadSSL-1.57 {superfish} -body { + badssl superfish.badssl.com + } -result {handshake failed: certificate verify failed due to "unable to get local issuer certificate"} -returnCodes {1} + +test BadSSL-1.58 {tls-v1-0:1010} -constraints {tls1 old_api} -body { + badssl tls-v1-0.badssl.com:1010 + } + +test BadSSL-1.59 {tls-v1-0:1010} -constraints {tls1 new_api} -body { + badssl tls-v1-0.badssl.com:1010 + } -result {handshake failed: unsupported protocol} -returnCodes {1} + +test BadSSL-1.60 {tls-v1-1:1011} -constraints {tls1.1 old_api} -body { + badssl tls-v1-1.badssl.com:1011 + } + +test BadSSL-1.61 {tls-v1-1:1011} -constraints {tls1.1 new_api} -body { + badssl tls-v1-1.badssl.com:1011 + } -result {handshake failed: unsupported protocol} -returnCodes {1} + +test BadSSL-1.62 {tls-v1-2:1012} -constraints {tls1.2} -body { + badssl tls-v1-2.badssl.com:1012 + } + +test BadSSL-1.63 {untrusted-root} -constraints {old_api} -body { + badssl untrusted-root.badssl.com + } -result {handshake failed: certificate verify failed due to "self signed certificate in certificate chain"} -returnCodes {1} + +test BadSSL-1.64 {untrusted-root} -constraints {new_api} -body { + badssl untrusted-root.badssl.com + } -result {handshake failed: certificate verify failed due to "self-signed certificate in certificate chain"} -returnCodes {1} + +test BadSSL-1.65 {upgrade} -body { + badssl upgrade.badssl.com + } + +test BadSSL-1.66 {webpack-dev-server} -body { + badssl webpack-dev-server.badssl.com + } -result {handshake failed: certificate verify failed due to "unable to get local issuer certificate"} -returnCodes {1} + +test BadSSL-1.67 {wrong.host} -constraints {old_api} -body { + badssl wrong.host.badssl.com + } -result {handshake failed: certificate verify failed due to "Hostname mismatch"} -returnCodes {1} + +test BadSSL-1.68 {wrong.host} -constraints {new_api} -body { + badssl wrong.host.badssl.com + } -result {handshake failed: certificate verify failed due to "hostname mismatch"} -returnCodes {1} + +test BadSSL-1.69 {mozilla-modern} -body { badssl mozilla-modern.badssl.com } # Cleanup ::tcltest::cleanupTests return Index: tests/ciphers.csv ================================================================== --- tests/ciphers.csv +++ tests/ciphers.csv @@ -9,38 +9,53 @@ command,foreach protocol $protocols {::tcltest::testConstraint $protocol 0},,,,,,,,, command,foreach protocol [::tls::protocols] {::tcltest::testConstraint $protocol 1},,,,,,,,, command,"::tcltest::testConstraint OpenSSL [string match ""OpenSSL*"" [::tls::version]]",,,,,,,,, ,,,,,,,,,, command,# Helper functions,,,,,,,,, -command,"proc lcompare {list1 list2} {set m """";set u """";foreach i $list1 {if {$i ni $list2} {lappend m $i}};foreach i $list2 {if {$i ni $list1} {lappend u $i}};return [list ""missing"" $m ""unexpected"" $u]}",,,,,,,,, +command,"proc lcompare {list1 list2} { + set m """" + set u """" + foreach i $list1 { + if {$i ni $list2} { + lappend m $i + } + } + foreach i $list2 { + if {$i ni $list1} { + lappend u $i + } + } + return [list ""missing"" $m ""unexpected"" $u] +} +",,,,,,,,, command,proc exec_get {delim args} {return [split [exec openssl {*}$args] $delim]},,,,,,,,, ,,,,,,,,,, command,# Test protocols,,,,,,,,, Protocols,All,,,lcompare $protocols [::tls::protocols],,,missing {ssl2 ssl3} unexpected {},,, ,,,,,,,,,, command,# Test ciphers,,,,,,,,, -CiphersAll,SSL2,ssl2,,"lcompare [exec_get "":"" ciphers -ssl2] [::tls::ciphers ssl2]",,,missing {} unexpected {},,, -CiphersAll,SSL3,ssl3,,"lcompare [exec_get "":"" ciphers -ssl3] [::tls::ciphers ssl3]",,,missing {} unexpected {},,, -CiphersAll,TLS1,tls1,,"lcompare [exec_get "":"" ciphers -tls1] [::tls::ciphers tls1]",,,missing {} unexpected {},,, -CiphersAll,TLS1.1,tls1.1,,"lcompare [exec_get "":"" ciphers -tls1_1] [::tls::ciphers tls1.1]",,,missing {} unexpected {},,, -CiphersAll,TLS1.2,tls1.2,,"lcompare [exec_get "":"" ciphers -tls1_2] [::tls::ciphers tls1.2]",,,missing {} unexpected {},,, -CiphersAll,TLS1.3,tls1.3,,"lcompare [exec_get "":"" ciphers -tls1_3] [::tls::ciphers tls1.3]",,,missing {} unexpected {},,, +Ciphers By Protocol,SSL2,ssl2,,"lcompare [exec_get "":"" ciphers -ssl2] [::tls::ciphers ssl2]",,,missing {} unexpected {},,, +Ciphers By Protocol,SSL3,ssl3,,"lcompare [exec_get "":"" ciphers -ssl3] [::tls::ciphers ssl3]",,,missing {} unexpected {},,, +Ciphers By Protocol,TLS1.0,tls1,,"lcompare [exec_get "":"" ciphers -tls1] [::tls::ciphers tls1]",,,missing {} unexpected {},,, +Ciphers By Protocol,TLS1.1,tls1.1,,"lcompare [exec_get "":"" ciphers -tls1_1] [::tls::ciphers tls1.1]",,,missing {} unexpected {},,, +Ciphers By Protocol,TLS1.2,tls1.2,,"lcompare [exec_get "":"" ciphers -tls1_2] [::tls::ciphers tls1.2]",,,missing {} unexpected {},,, +Ciphers By Protocol,TLS1.3,tls1.3,,"lcompare [exec_get "":"" ciphers -tls1_3] [::tls::ciphers tls1.3]",,,missing {} unexpected {},,, ,,,,,,,,,, command,# Test cipher descriptions,,,,,,,,, -CiphersDesc,SSL2,ssl2,,"lcompare [exec_get ""\r\n"" ciphers -ssl2 -v] [split [string trim [::tls::ciphers ssl2 1]] \n]",,,missing {} unexpected {},,, -CiphersDesc,SSL3,ssl3,,"lcompare [exec_get ""\r\n"" ciphers -ssl3 -v] [split [string trim [::tls::ciphers ssl3 1]] \n]",,,missing {} unexpected {},,, -CiphersDesc,TLS1,tls1,,"lcompare [exec_get ""\r\n"" ciphers -tls1 -v] [split [string trim [::tls::ciphers tls1 1]] \n]",,,missing {} unexpected {},,, -CiphersDesc,TLS1.1,tls1.1,,"lcompare [exec_get ""\r\n"" ciphers -tls1_1 -v] [split [string trim [::tls::ciphers tls1.1 1]] \n]",,,missing {} unexpected {},,, -CiphersDesc,TLS1.2,tls1.2,,"lcompare [exec_get ""\r\n"" ciphers -tls1_2 -v] [split [string trim [::tls::ciphers tls1.2 1]] \n]",,,missing {} unexpected {},,, -CiphersDesc,TLS1.3,tls1.3,,"lcompare [exec_get ""\r\n"" ciphers -tls1_3 -v] [split [string trim [::tls::ciphers tls1.3 1]] \n]",,,missing {} unexpected {},,, +Ciphers With Descriptions,SSL2,ssl2,,"lcompare [exec_get ""\r\n"" ciphers -ssl2 -v] [split [string trim [::tls::ciphers ssl2 1]] \n]",,,missing {} unexpected {},,, +Ciphers With Descriptions,SSL3,ssl3,,"lcompare [exec_get ""\r\n"" ciphers -ssl3 -v] [split [string trim [::tls::ciphers ssl3 1]] \n]",,,missing {} unexpected {},,, +Ciphers With Descriptions,TLS1.0,tls1,,"lcompare [exec_get ""\r\n"" ciphers -tls1 -v] [split [string trim [::tls::ciphers tls1 1]] \n]",,,missing {} unexpected {},,, +Ciphers With Descriptions,TLS1.1,tls1.1,,"lcompare [exec_get ""\r\n"" ciphers -tls1_1 -v] [split [string trim [::tls::ciphers tls1.1 1]] \n]",,,missing {} unexpected {},,, +Ciphers With Descriptions,TLS1.2,tls1.2,,"lcompare [exec_get ""\r\n"" ciphers -tls1_2 -v] [split [string trim [::tls::ciphers tls1.2 1]] \n]",,,missing {} unexpected {},,, +Ciphers With Descriptions,TLS1.3,tls1.3,,"lcompare [exec_get ""\r\n"" ciphers -tls1_3 -v] [split [string trim [::tls::ciphers tls1.3 1]] \n]",,,missing {} unexpected {},,, ,,,,,,,,,, command,# Test protocol specific ciphers,,,,,,,,, -CiphersSpecific,SSL2,ssl2,,"lcompare [exec_get "":"" ciphers -ssl2 -s] [::tls::ciphers ssl2 0 1]",,,missing {} unexpected {},,, -CiphersSpecific,SSL3,ssl3,,"lcompare [exec_get "":"" ciphers -ssl3 -s] [::tls::ciphers ssl3 0 1]",,,missing {} unexpected {},,, -CiphersSpecific,TLS1,tls1,,"lcompare [exec_get "":"" ciphers -tls1 -s] [::tls::ciphers tls1 0 1]",,,missing {} unexpected {},,, -CiphersSpecific,TLS1.1,tls1.1,,"lcompare [exec_get "":"" ciphers -tls1_1 -s] [::tls::ciphers tls1.1 0 1]",,,missing {} unexpected {},,, -CiphersSpecific,TLS1.2,tls1.2,,"lcompare [exec_get "":"" ciphers -tls1_2 -s] [::tls::ciphers tls1.2 0 1]",,,missing {} unexpected {},,, -CiphersSpecific,TLS1.3,tls1.3,,"lcompare [exec_get "":"" ciphers -tls1_3 -s] [::tls::ciphers tls1.3 0 1]",,,missing {} unexpected {},,, +Ciphers Protocol Specific,SSL2,ssl2,,"lcompare [exec_get "":"" ciphers -ssl2 -s] [::tls::ciphers ssl2 0 1]",,,missing {} unexpected {},,, +Ciphers Protocol Specific,SSL3,ssl3,,"lcompare [exec_get "":"" ciphers -ssl3 -s] [::tls::ciphers ssl3 0 1]",,,missing {} unexpected {},,, +Ciphers Protocol Specific,TLS1.0,tls1,,"lcompare [exec_get "":"" ciphers -tls1 -s] [::tls::ciphers tls1 0 1]",,,missing {} unexpected {},,, +Ciphers Protocol Specific,TLS1.1,tls1.1,,"lcompare [exec_get "":"" ciphers -tls1_1 -s] [::tls::ciphers tls1.1 0 1]",,,missing {} unexpected {},,, +Ciphers Protocol Specific,TLS1.2,tls1.2,,"lcompare [exec_get "":"" ciphers -tls1_2 -s] [::tls::ciphers tls1.2 0 1]",,,missing {} unexpected {},,, +Ciphers Protocol Specific,TLS1.3,tls1.3,,"lcompare [exec_get "":"" ciphers -tls1_3 -s] [::tls::ciphers tls1.3 0 1]",,,missing {} unexpected {},,, ,,,,,,,,,, command,# Test version,,,,,,,,, Version,All,,,::tls::version,,glob,*,,, Version,OpenSSL,OpenSSL,,::tls::version,,glob,OpenSSL*,,, Index: tests/ciphers.test ================================================================== --- tests/ciphers.test +++ tests/ciphers.test @@ -1,6 +1,6 @@ -# Auto generated test cases for ciphers_and_protocols.csv +# Auto generated test cases for ciphers.csv # Load Tcl Test package if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest namespace import ::tcltest::* @@ -16,19 +16,22 @@ # Constraints set protocols [list ssl2 ssl3 tls1 tls1.1 tls1.2 tls1.3] foreach protocol $protocols {::tcltest::testConstraint $protocol 0} foreach protocol [::tls::protocols] {::tcltest::testConstraint $protocol 1} ::tcltest::testConstraint OpenSSL [string match "OpenSSL*" [::tls::version]] + # Helper functions proc lcompare {list1 list2} {set m "";set u "";foreach i $list1 {if {$i ni $list2} {lappend m $i}};foreach i $list2 {if {$i ni $list1} {lappend u $i}};return [list "missing" $m "unexpected" $u]} proc exec_get {delim args} {return [split [exec openssl {*}$args] $delim]} + # Test protocols test Protocols-1.1 {All} -body { lcompare $protocols [::tls::protocols] } -result {missing {ssl2 ssl3} unexpected {}} + # Test ciphers test CiphersAll-2.1 {SSL2} -constraints {ssl2} -body { lcompare [exec_get ":" ciphers -ssl2] [::tls::ciphers ssl2] @@ -51,10 +54,11 @@ } -result {missing {} unexpected {}} test CiphersAll-2.6 {TLS1.3} -constraints {tls1.3} -body { lcompare [exec_get ":" ciphers -tls1_3] [::tls::ciphers tls1.3] } -result {missing {} unexpected {}} + # Test cipher descriptions test CiphersDesc-3.1 {SSL2} -constraints {ssl2} -body { lcompare [exec_get "\r\n" ciphers -ssl2 -v] [split [string trim [::tls::ciphers ssl2 1]] \n] @@ -77,10 +81,11 @@ } -result {missing {} unexpected {}} test CiphersDesc-3.6 {TLS1.3} -constraints {tls1.3} -body { lcompare [exec_get "\r\n" ciphers -tls1_3 -v] [split [string trim [::tls::ciphers tls1.3 1]] \n] } -result {missing {} unexpected {}} + # Test protocol specific ciphers test CiphersSpecific-4.1 {SSL2} -constraints {ssl2} -body { lcompare [exec_get ":" ciphers -ssl2 -s] [::tls::ciphers ssl2 0 1] @@ -103,10 +108,11 @@ } -result {missing {} unexpected {}} test CiphersSpecific-4.6 {TLS1.3} -constraints {tls1.3} -body { lcompare [exec_get ":" ciphers -tls1_3 -s] [::tls::ciphers tls1.3 0 1] } -result {missing {} unexpected {}} + # Test version test Version-5.1 {All} -body { ::tls::version Index: tests/keytest1.tcl ================================================================== --- tests/keytest1.tcl +++ tests/keytest1.tcl @@ -1,8 +1,6 @@ -#!/bin/sh -# The next line is executed by /bin/sh, but not tcl \ -exec tclsh "$0" ${1+"$@"} +#!/usr/bin/env tclsh set auto_path [linsert $auto_path 0 [file normalize [file join [file dirname [info script]] ..]]] package require tls proc creadable {s} { Index: tests/keytest2.tcl ================================================================== --- tests/keytest2.tcl +++ tests/keytest2.tcl @@ -1,8 +1,6 @@ -#!/bin/sh -# The next line is executed by /bin/sh, but not tcl \ -exec tclsh "$0" ${1+"$@"} +#! /usr/bin/env tclsh set auto_path [linsert $auto_path 0 [file normalize [file join [file dirname [info script]] ..]]] package require tls set s [tls::socket 127.0.0.1 12300] Index: tests/make_test_files.tcl ================================================================== --- tests/make_test_files.tcl +++ tests/make_test_files.tcl @@ -1,15 +1,67 @@ # # Name: Make Test Files From CSV Files -# Version: 0.2 -# Date: August 6, 2022 +# Version: 0.3 +# Date: March 9, 2024 # Author: Brian O'Hagan # Email: brian199@comcast.net # Legal Notice: (c) Copyright 2020 by Brian O'Hagan # Released under the Apache v2.0 license. I would appreciate a copy of any modifications # made to this package for possible incorporation in a future release. # + +# +# Parse CSV line +# +proc parse_csv {ch data} { + set buffer "" + set result [list] + set start 0 + set end [string length $data] + + while {$start < $end} { + if {[string index $data $start] eq "\""} { + # Quoted + if {[set index [string first "\"" $data [incr start]]] > -1} { + set next [string index $data [expr {$index + 1}]] + if {$next eq "\""} { + # Quote + append buffer [string range $data $start $index] + set start [incr index] + + } else { + # End of quoted data + append buffer [string range $data $start [incr index -1]] + set start [incr index 3] + lappend result $buffer + set buffer "" + } + + } else { + # Multi-line + append buffer [string range $data $start end] "\n" + gets $ch new + set data "\"" + append data $new + set start 0 + set end [string length $data] + } + + } else { + # Not quoted, so no embedded NL, quotes, or commas + set index [string first "," $data $start] + if {$index > -1} { + lappend result [string range $data $start [incr index -1]] + set start [incr index 2] + } else { + lappend result [string range $data $start end] + set start [string length $data] + } + } + } + return $result +} # # Convert test case file into test files # proc process_config_file {filename} { @@ -37,34 +89,16 @@ # Generate test cases and add to test file while {[gets $in data] > -1} { # Skip comments set data [string trim $data] if {[string match "#*" $data]} continue - # Split comma separated fields with quotes - set list [list] - while {[string length $data] > 0} { - if {[string index $data 0] eq "\""} { - # Quoted - set end [string first "\"," $data] - if {$end == -1} {set end [expr {[string length $data]+1}]} - lappend list [string map [list {""} \"] [string range $data 1 [incr end -1]]] - set data [string range $data [incr end 3] end] - - } else { - # Not quoted, so no embedded NL, quotes, or commas - set index [string first "," $data] - if {$index == -1} {set index [expr {[string length $data]+1}]} - lappend list [string range $data 0 [incr index -1]] - set data [string range $data [incr index 2] end] - } - } + set list [parse_csv $in $data] # Get command or test case foreach {group name constraints setup body cleanup match result output errorOutput returnCodes} $list { if {$group eq "command"} { - # Pass-through command puts $out $name } elseif {$group ne "" && $body ne ""} { set group [string map [list " " "_"] $group] if {$group ne $prev} { @@ -72,11 +106,16 @@ set prev $group puts $out "" } # Test case - set buffer [format "\ntest %s-%d.%d {%s}" $group $test [incr cases($group)] $name] + if {[string index $name 0] ne {$}} { + set buffer [format "\ntest %s-%d.%d {%s}" $group $test [incr cases($group)] $name] + } else { + set buffer [format "\ntest %s-%d.%d %s" $group $test [incr cases($group)] $name] + } + foreach opt [list -constraints -setup -body -cleanup -match -result -output -errorOutput -returnCodes] { set cmd [string trim [set [string trimleft $opt "-"]]] if {$cmd ne ""} { if {$opt in [list -setup -body -cleanup]} { append buffer " " $opt " \{\n" @@ -85,11 +124,11 @@ } append buffer " \}" } elseif {$opt in [list -output -errorOutput]} { append buffer " " $opt " {" $cmd \n "}" } elseif {$opt in [list -result]} { - if {[string index $cmd 0] in [list \[ \" \{]} { + if {[string index $cmd 0] in [list \[ \" \{ \$]} { append buffer " " $opt " " $cmd } elseif {[string match {*[\\$]*} $cmd]} { append buffer " " $opt " \"" [string map [list \\\\\" \\\"] [string map [list \" \\\" ] $cmd]] "\"" } else { append buffer " " $opt " {" $cmd "}" @@ -101,10 +140,11 @@ } puts $out $buffer } else { # Empty line + puts $out "" } break } } @@ -116,8 +156,9 @@ # # Call script # foreach file [glob *.csv] { +puts $file process_config_file $file } exit Index: tests/simpleClient.tcl ================================================================== --- tests/simpleClient.tcl +++ tests/simpleClient.tcl @@ -1,8 +1,6 @@ -#!/bin/sh -# The next line is executed by /bin/sh, but not tcl \ -exec tclsh "$0" ${1+"$@"} +#!/usr/bin/env tclsh package require tls set dir [file join [file dirname [info script]] ../tests/certs] set OPTS(-cafile) [file join $dir ca.pem] Index: tests/simpleServer.tcl ================================================================== --- tests/simpleServer.tcl +++ tests/simpleServer.tcl @@ -1,8 +1,6 @@ -#!/bin/sh -# The next line is executed by /bin/sh, but not tcl \ -exec tclsh "$0" ${1+"$@"} +#!/usr/bin/env tclsh package require tls set dir [file join [file dirname [info script]] ../tests/certs] set OPTS(-cafile) [file join $dir ca.pem]