summaryrefslogtreecommitdiffstats
path: root/tests/auto/network/ssl
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/network/ssl')
-rw-r--r--tests/auto/network/ssl/qsslcertificate/.gitignore1
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/ca-cert.pem33
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/ca-cert.pem.digest-md51
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/ca-cert.pem.digest-sha11
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert-ss-san-utf8.pem16
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert-ss-san-utf8.pem.san5
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert-ss-san.pem13
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert-ss-san.pem.san5
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.derbin0 -> 461 bytes
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.der.pubkeybin0 -> 162 bytes
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.pem12
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.pem.digest-md51
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.pem.digest-sha11
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.pem.pubkey6
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert.derbin0 -> 503 bytes
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert.der.pubkeybin0 -> 162 bytes
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert.pem13
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert.pem.digest-md51
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert.pem.digest-sha11
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/cert.pem.pubkey6
-rwxr-xr-xtests/auto/network/ssl/qsslcertificate/certificates/gencertificates.sh104
-rw-r--r--tests/auto/network/ssl/qsslcertificate/certificates/san.cnf5
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/badguy-nul-cn.crt81
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/badguy-nul-san.crt83
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted-google.com-diginotar.pem30
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted1.pem19
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted2.pem19
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted3.pem19
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted4.pem19
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted5.pem19
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted6.pem19
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted7.pem19
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted8.pem19
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted9.pem19
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/cert-large-expiration-date.pem15
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/cert-large-expiration-date.txt.0.9.842
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/cert-large-expiration-date.txt.1.0.042
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/cert-large-serial-number.pem14
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/malformed-just-begin-no-newline.pem1
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/malformed-just-begin.pem1
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/natwest-banking.pem36
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/no-ending-newline.pem13
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/test-cn-two-cns-cert.pem67
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/test-cn-with-drink-cert.pem66
-rw-r--r--tests/auto/network/ssl/qsslcertificate/more-certificates/trailing-whitespace.pem13
-rw-r--r--tests/auto/network/ssl/qsslcertificate/qsslcertificate.pro29
-rw-r--r--tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp995
-rw-r--r--tests/auto/network/ssl/qsslcertificate/verify-certs/README2
-rw-r--r--tests/auto/network/ssl/qsslcertificate/verify-certs/cacert.pem23
-rw-r--r--tests/auto/network/ssl/qsslcertificate/verify-certs/test-addons-mozilla-org-cert.pem34
-rw-r--r--tests/auto/network/ssl/qsslcertificate/verify-certs/test-intermediate-ca-cert.pem66
-rw-r--r--tests/auto/network/ssl/qsslcertificate/verify-certs/test-intermediate-is-ca-cert.pem53
-rw-r--r--tests/auto/network/ssl/qsslcertificate/verify-certs/test-intermediate-not-ca-cert.pem54
-rw-r--r--tests/auto/network/ssl/qsslcertificate/verify-certs/test-ocsp-good-cert.pem67
-rw-r--r--tests/auto/network/ssl/qsslcipher/.gitignore1
-rw-r--r--tests/auto/network/ssl/qsslcipher/qsslcipher.pro18
-rw-r--r--tests/auto/network/ssl/qsslcipher/tst_qsslcipher.cpp101
-rw-r--r--tests/auto/network/ssl/qsslerror/.gitignore1
-rw-r--r--tests/auto/network/ssl/qsslerror/qsslerror.pro18
-rw-r--r--tests/auto/network/ssl/qsslerror/tst_qsslerror.cpp122
-rw-r--r--tests/auto/network/ssl/qsslkey/.gitignore1
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-1024.derbin0 -> 447 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-1024.pem12
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512.derbin0 -> 251 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-512.pem8
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-576.derbin0 -> 275 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-576.pem8
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-960.derbin0 -> 419 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pri-960.pem11
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pub-1024.derbin0 -> 442 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pub-1024.pem12
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pub-512.derbin0 -> 244 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pub-512.pem8
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pub-576.derbin0 -> 268 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pub-576.pem8
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pub-960.derbin0 -> 414 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/dsa-pub-960.pem11
-rwxr-xr-xtests/auto/network/ssl/qsslkey/keys/genkeys.sh82
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-1023.derbin0 -> 605 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-1023.pem15
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-1024.derbin0 -> 608 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-1024.pem15
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-2048.derbin0 -> 1190 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-2048.pem27
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-40.derbin0 -> 49 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-40.pem4
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-511.derbin0 -> 316 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-511.pem9
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512.derbin0 -> 320 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-512.pem9
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-999.derbin0 -> 591 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pri-999.pem15
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-1023.derbin0 -> 161 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-1023.pem6
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-1024.derbin0 -> 162 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-1024.pem6
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-2048.derbin0 -> 294 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-2048.pem9
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-40.derbin0 -> 35 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-40.pem3
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-511.derbin0 -> 93 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-511.pem4
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-512.derbin0 -> 94 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-512.pem4
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-999.derbin0 -> 157 bytes
-rw-r--r--tests/auto/network/ssl/qsslkey/keys/rsa-pub-999.pem6
-rw-r--r--tests/auto/network/ssl/qsslkey/qsslkey.pro32
-rw-r--r--tests/auto/network/ssl/qsslkey/rsa-with-passphrase.pem18
-rw-r--r--tests/auto/network/ssl/qsslkey/rsa-without-passphrase.pem15
-rw-r--r--tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp447
-rw-r--r--tests/auto/network/ssl/qsslsocket/.gitignore1
-rw-r--r--tests/auto/network/ssl/qsslsocket/certs/aspiriniks.ca.crt22
-rw-r--r--tests/auto/network/ssl/qsslsocket/certs/fake-login.live.com.key15
-rw-r--r--tests/auto/network/ssl/qsslsocket/certs/fake-login.live.com.pem19
-rw-r--r--tests/auto/network/ssl/qsslsocket/certs/fluke.cert75
-rw-r--r--tests/auto/network/ssl/qsslsocket/certs/fluke.key15
-rw-r--r--tests/auto/network/ssl/qsslsocket/certs/qt-test-server-cacert.pem17
-rw-r--r--tests/auto/network/ssl/qsslsocket/qsslsocket.pro48
-rw-r--r--tests/auto/network/ssl/qsslsocket/ssl.tar.gzbin0 -> 36299 bytes
-rw-r--r--tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp2097
-rw-r--r--tests/auto/network/ssl/ssl.pro8
121 files changed, 5606 insertions, 0 deletions
diff --git a/tests/auto/network/ssl/qsslcertificate/.gitignore b/tests/auto/network/ssl/qsslcertificate/.gitignore
new file mode 100644
index 0000000000..25b34756b7
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/.gitignore
@@ -0,0 +1 @@
+tst_qsslcertificate
diff --git a/tests/auto/network/ssl/qsslcertificate/certificates/ca-cert.pem b/tests/auto/network/ssl/qsslcertificate/certificates/ca-cert.pem
new file mode 100644
index 0000000000..bcba68aefa
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/certificates/ca-cert.pem
@@ -0,0 +1,33 @@
+-----BEGIN CERTIFICATE-----
+MIIC5TCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQQFADBcMQswCQYDVQQGEwJBVTET
+MBEGA1UECBMKUXVlZW5zbGFuZDEaMBgGA1UEChMRQ3J5cHRTb2Z0IFB0eSBMdGQx
+HDAaBgNVBAMTE1Rlc3QgUENBICgxMDI0IGJpdCkwHhcNOTkxMjAyMjEzODUxWhcN
+MDUwNzEwMjEzODUxWjBbMQswCQYDVQQGEwJBVTETMBEGA1UECBMKUXVlZW5zbGFu
+ZDEaMBgGA1UEChMRQ3J5cHRTb2Z0IFB0eSBMdGQxGzAZBgNVBAMTElRlc3QgQ0Eg
+KDEwMjQgYml0KTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAo7ujy3XXpU/p
+yDJtOxkMJmGv3mdiVm7JrdoKLUgqjO2rBaeNuYMUiuI6oYU+tlD6agwRML0Pn2JF
+b90VdK/UXrmRr9djaEuH17EIKjte5RwOzndCndsjcCYyoeODMTyg7dqPIkDMmRNM
+5R5xBTabD+Aji0wzQupYxBLuW5PLj7ECAwEAAaOBtzCBtDAdBgNVHQ4EFgQU1WWA
+U42mkhi3ecgey1dsJjU61+UwgYQGA1UdIwR9MHuAFE0RaEcrj18q1dw+G6nJbsTW
+R213oWCkXjBcMQswCQYDVQQGEwJBVTETMBEGA1UECBMKUXVlZW5zbGFuZDEaMBgG
+A1UEChMRQ3J5cHRTb2Z0IFB0eSBMdGQxHDAaBgNVBAMTE1Rlc3QgUENBICgxMDI0
+IGJpdCmCAQAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQBb39BRphHL
+6aRAQyymsvBvPSCiG9+kR0R1L23aTpNbhXp2BebyFjbEQYZc2kWGiKKcHkNECA35
+3d4LoqUlVey8DFyafOIJd9hxdZfg+rxlHMxnL7uCJRmx9+xB411Jtsol9/wg1uCK
+sleGpgB4j8cG2SVCz7V2MNZNK+d5QCnR7A==
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQCju6PLddelT+nIMm07GQwmYa/eZ2JWbsmt2gotSCqM7asFp425
+gxSK4jqhhT62UPpqDBEwvQ+fYkVv3RV0r9ReuZGv12NoS4fXsQgqO17lHA7Od0Kd
+2yNwJjKh44MxPKDt2o8iQMyZE0zlHnEFNpsP4COLTDNC6ljEEu5bk8uPsQIDAQAB
+AoGAVZmpFZsDZfr0l2S9tLLwpjRWNOlKATQkno6q2WesT0eGLQufTciY+c8ypfU6
+hyio8r5iUl/VhhdjhAtKx1mRpiotftHo/eYf8rtsrnprOnWG0bWjLjtIoMbcxGn2
+J3bN6LJmbJMjDs0eJ3KnTu646F3nDUw2oGAwmpzKXA1KAP0CQQDRvQhxk2D3Pehs
+HvG665u2pB5ipYQngEFlZO7RHJZzJOZEWSLuuMqaF/7pTfA5jiBvWqCgJeCRRInL
+21ru4dlPAkEAx9jj7BgKn5TYnMoBSSe0afjsV9oApVpN1Nacb1YDtCwy+scp3++s
+nFxlv98wxIlSdpwMUn+AUWfjiWR7Tu/G/wJBAJ/KjwZIrFVxewP0x2ILYsTRYLzz
+MS4PDsO7FB+I0i7DbBOifXS2oNSpd3I0CNMwrxFnUHzynpbOStVfN3ZL5w0CQQCa
+pwFahxBRhkJKsxhjoFJBX9yl75JoY4Wvm5Tbo9ih6UJaRx3kqfkN14L2BKYcsZgb
+KY9vmDOYy6iNfjDeWTfJAkBkfPUb8oTJ/nSP5zN6sqGxSY4krc4xLxpRmxoJ8HL2
+XfhqXkTzbU13RX9JJ/NZ8vQN9Vm2NhxRGJocQkmcdVtJ
+-----END RSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslcertificate/certificates/ca-cert.pem.digest-md5 b/tests/auto/network/ssl/qsslcertificate/certificates/ca-cert.pem.digest-md5
new file mode 100644
index 0000000000..800a05b030
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/certificates/ca-cert.pem.digest-md5
@@ -0,0 +1 @@
+MD5 Fingerprint=EF:02:83:EA:AC:AF:6A:D0:8D:4F:56:A8:2B:A1:C5:D3
diff --git a/tests/auto/network/ssl/qsslcertificate/certificates/ca-cert.pem.digest-sha1 b/tests/auto/network/ssl/qsslcertificate/certificates/ca-cert.pem.digest-sha1
new file mode 100644
index 0000000000..df311a8dcb
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/certificates/ca-cert.pem.digest-sha1
@@ -0,0 +1 @@
+SHA1 Fingerprint=A6:CC:2A:D7:E3:8F:49:E7:8B:4F:76:E8:E0:FA:37:5E:62:2F:66:23
diff --git a/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss-san-utf8.pem b/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss-san-utf8.pem
new file mode 100644
index 0000000000..e1b731d69b
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss-san-utf8.pem
@@ -0,0 +1,16 @@
+-----BEGIN CERTIFICATE-----
+MIICkTCCAfqgAwIBAgIJAL1nF+PLAF2KMA0GCSqGSIb3DQEBBQUAMGkxKzApBgNV
+BAoMIkjElcSCxrLDvyDKjeG6v8qI4bq34bi7IFLDqWPDtnJkxZ0xFTATBgNVBAsM
+DOOIp0HjiYHvvatCQzEWMBQGA1UEAwwNSm9obm55IEd1aXRhcjELMAkGA1UEBhMC
+Tk8wHhcNMTEwNTA1MDgxMzEwWhcNMTEwNjA0MDgxMzEwWjBpMSswKQYDVQQKDCJI
+xJXEgsayw78gyo3hur/KiOG6t+G4uyBSw6ljw7ZyZMWdMRUwEwYDVQQLDAzjiKdB
+44mB772rQkMxFjAUBgNVBAMMDUpvaG5ueSBHdWl0YXIxCzAJBgNVBAYTAk5PMIGf
+MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC2zSxS17I6596dJE/VAmGz+06D9S8n
+3C0hnIGNVu+LwbgDJTvOw0SzNj4UP72UGgd3UI1KLBg5XWIsRNmE3COJMMh6syjI
+L1Ept+tVXxGL6n4gl+0nZ7dkUyxJmeFtigYrL+qCH1yd5rmf3sC3jO4IosuAiG66
+IDkJEVo64NT8ZQIDAQABo0EwPzA9BgNVHREENjA0gQ9hcm5lQGZvb2Jhci5vcmeC
+Dnd3dy5mb29iYXIub3JngRFiamFybmVAZm9vYmFyLm9yZzANBgkqhkiG9w0BAQUF
+AAOBgQAqVhbC0/EUFdnKlYV3PrknwGX1dPEPGJuIQHa0KpoicvNiOhs1HxBDYbzc
+F6wcAMEynq4YwGKhcQLZOs2mo0LreAjA9rU/yBnqrnUW/4gxtUUvmJKK+62IjfLp
+eO1L+1NcEMJiaZf8fip4VXhXdOYUhgE8WUZ1UJRC6w3T/yAgcQ==
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss-san-utf8.pem.san b/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss-san-utf8.pem.san
new file mode 100644
index 0000000000..f46a637da4
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss-san-utf8.pem.san
@@ -0,0 +1,5 @@
+[subj_alt_name]
+subjectAltName=\
+ email:arne@foobar.org,\
+ DNS:www.foobar.org,\
+ email:bjarne@foobar.org
diff --git a/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss-san.pem b/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss-san.pem
new file mode 100644
index 0000000000..3d0bdfcee8
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss-san.pem
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIIB9zCCAWCgAwIBAgIJAIyyZjJFdeyIMA0GCSqGSIb3DQEBBQUAMBwxGjAYBgNV
+BAMTEUpvaG5ueSBHdWl0YXJDPU5PMB4XDTA3MDQyMDEwMzIzOVoXDTA3MDUyMDEw
+MzIzOVowHDEaMBgGA1UEAxMRSm9obm55IEd1aXRhckM9Tk8wgZ8wDQYJKoZIhvcN
+AQEBBQADgY0AMIGJAoGBANPgV/8gMg5Gh4vhfcoUTHXTqhcEuCh5VE/h57Ea7uj4
+1/bQtUNUvRZO21KtAmLHkFLoNQqeYbFJ4ZP7u/R/WDNk76EQtYNcMmJgSu/QRlxj
+bEFFBOPPflQH7nYdneMegszzijRQ25oZhnjbyI0xZgqpNZwipBkC5lPgsrmlOckd
+AgMBAAGjQTA/MD0GA1UdEQQ2MDSBD2FybmVAZm9vYmFyLm9yZ4IOd3d3LmZvb2Jh
+ci5vcmeBEWJqYXJuZUBmb29iYXIub3JnMA0GCSqGSIb3DQEBBQUAA4GBAFVqCnFr
+5EevQiVtAbDlTSbTJ3XWJSzjU0yf+tNYvPEIEqoDVh25YhSNWqRCMYFiUomj55WY
+Rf7C4JM/eRlo99xnR4OtJzfLi+q1eKhl53cuwooajRjVOxQsdHpke51L9UzibKGw
+0o8D/FNBw+D4GwIC1sdKw2UWAeaMhNzSEWKA
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss-san.pem.san b/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss-san.pem.san
new file mode 100644
index 0000000000..f46a637da4
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss-san.pem.san
@@ -0,0 +1,5 @@
+[subj_alt_name]
+subjectAltName=\
+ email:arne@foobar.org,\
+ DNS:www.foobar.org,\
+ email:bjarne@foobar.org
diff --git a/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.der b/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.der
new file mode 100644
index 0000000000..ea9eedc643
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.der.pubkey b/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.der.pubkey
new file mode 100644
index 0000000000..48d2b99c3a
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.der.pubkey
Binary files differ
diff --git a/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.pem b/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.pem
new file mode 100644
index 0000000000..b2626f3d1a
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.pem
@@ -0,0 +1,12 @@
+-----BEGIN CERTIFICATE-----
+MIIByTCCATICCQDiwxj6Xps7zDANBgkqhkiG9w0BAQUFADApMRowGAYDVQQDExFu
+YW1lL3dpdGgvc2xhc2hlczELMAkGA1UEBhMCTk8wHhcNMDcwNDE3MDc0MDI2WhcN
+MDcwNTE3MDc0MDI2WjApMRowGAYDVQQDExFuYW1lL3dpdGgvc2xhc2hlczELMAkG
+A1UEBhMCTk8wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOud6QOsME+pWANE
+xxgmL0iT1ayg++hTxHsqAYnm/FoMxfUh+NdKkgJn2/GfNppinfPOSI667VqonU+7
+JBZDTLV5CPbZIo9fFQpDJQN6naev4yaxU1VeYFfI7S8c8zYKeGSR+RenNNeLvfH8
+0YxPpZZ1snv8IfDH2V8MVxiyr7lLAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAT9Kz
+0kg75nMzcg23J0q6OGvkj0VO6QOaAwqt6v+Kp5kgOzUEisbVt9oxZrWwkEw6dFNN
+cl7Blq6HQm6beezJobhEsi3G8OjVBrTDFb+jqPi/kwXuKL3QyfY2r/LRuINGrBDi
+Ewg7KuI0qZPe0bQ9NCM5TCD6qCj4vx3HdIHU4Ew=
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.pem.digest-md5 b/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.pem.digest-md5
new file mode 100644
index 0000000000..62f4d76072
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.pem.digest-md5
@@ -0,0 +1 @@
+MD5 Fingerprint=F4:2B:9D:73:2B:C8:26:56:60:9C:7F:58:66:07:4A:46
diff --git a/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.pem.digest-sha1 b/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.pem.digest-sha1
new file mode 100644
index 0000000000..02430ed89b
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.pem.digest-sha1
@@ -0,0 +1 @@
+SHA1 Fingerprint=B5:CF:31:AE:89:FB:BA:20:31:89:BA:71:06:7C:D7:84:9D:39:9E:46
diff --git a/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.pem.pubkey b/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.pem.pubkey
new file mode 100644
index 0000000000..5344d112cb
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/certificates/cert-ss.pem.pubkey
@@ -0,0 +1,6 @@
+-----BEGIN PUBLIC KEY-----
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDrnekDrDBPqVgDRMcYJi9Ik9Ws
+oPvoU8R7KgGJ5vxaDMX1IfjXSpICZ9vxnzaaYp3zzkiOuu1aqJ1PuyQWQ0y1eQj2
+2SKPXxUKQyUDep2nr+MmsVNVXmBXyO0vHPM2CnhkkfkXpzTXi73x/NGMT6WWdbJ7
+/CHwx9lfDFcYsq+5SwIDAQAB
+-----END PUBLIC KEY-----
diff --git a/tests/auto/network/ssl/qsslcertificate/certificates/cert.der b/tests/auto/network/ssl/qsslcertificate/certificates/cert.der
new file mode 100644
index 0000000000..aeb8571817
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/certificates/cert.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslcertificate/certificates/cert.der.pubkey b/tests/auto/network/ssl/qsslcertificate/certificates/cert.der.pubkey
new file mode 100644
index 0000000000..48d2b99c3a
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/certificates/cert.der.pubkey
Binary files differ
diff --git a/tests/auto/network/ssl/qsslcertificate/certificates/cert.pem b/tests/auto/network/ssl/qsslcertificate/certificates/cert.pem
new file mode 100644
index 0000000000..295010c210
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/certificates/cert.pem
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIIB8zCCAVwCAREwDQYJKoZIhvcNAQEFBQAwWzELMAkGA1UEBhMCQVUxEzARBgNV
+BAgTClF1ZWVuc2xhbmQxGjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMRswGQYD
+VQQDExJUZXN0IENBICgxMDI0IGJpdCkwHhcNMDcwNDE3MDc0MDI2WhcNMDcwNTE3
+MDc0MDI2WjApMRowGAYDVQQDExFuYW1lL3dpdGgvc2xhc2hlczELMAkGA1UEBhMC
+Tk8wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOud6QOsME+pWANExxgmL0iT
+1ayg++hTxHsqAYnm/FoMxfUh+NdKkgJn2/GfNppinfPOSI667VqonU+7JBZDTLV5
+CPbZIo9fFQpDJQN6naev4yaxU1VeYFfI7S8c8zYKeGSR+RenNNeLvfH80YxPpZZ1
+snv8IfDH2V8MVxiyr7lLAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAleaU4pgzV6KY
++q9QuXapUYMsC2GiNtDmkG3k+MTHUO8XlE4hqPrIM6rRf7zKQdZ950R2wL9FSnYl
+Qm1Tdv38dCka6ivMBqvRuOt9axH3m0G7nzHL7U3zaCbtEx3yVln+b3yYtiVpTuq0
+3MLrt7tQGAW6ra8ISf6YY1W65/uVXZE=
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/certificates/cert.pem.digest-md5 b/tests/auto/network/ssl/qsslcertificate/certificates/cert.pem.digest-md5
new file mode 100644
index 0000000000..5333f63f06
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/certificates/cert.pem.digest-md5
@@ -0,0 +1 @@
+MD5 Fingerprint=B6:CF:57:34:DA:A9:73:21:82:F7:CF:4D:3D:85:31:88
diff --git a/tests/auto/network/ssl/qsslcertificate/certificates/cert.pem.digest-sha1 b/tests/auto/network/ssl/qsslcertificate/certificates/cert.pem.digest-sha1
new file mode 100644
index 0000000000..62f84deb96
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/certificates/cert.pem.digest-sha1
@@ -0,0 +1 @@
+SHA1 Fingerprint=B6:D1:51:82:E0:29:CA:59:96:38:BD:B6:F9:40:05:91:6D:49:09:60
diff --git a/tests/auto/network/ssl/qsslcertificate/certificates/cert.pem.pubkey b/tests/auto/network/ssl/qsslcertificate/certificates/cert.pem.pubkey
new file mode 100644
index 0000000000..5344d112cb
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/certificates/cert.pem.pubkey
@@ -0,0 +1,6 @@
+-----BEGIN PUBLIC KEY-----
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDrnekDrDBPqVgDRMcYJi9Ik9Ws
+oPvoU8R7KgGJ5vxaDMX1IfjXSpICZ9vxnzaaYp3zzkiOuu1aqJ1PuyQWQ0y1eQj2
+2SKPXxUKQyUDep2nr+MmsVNVXmBXyO0vHPM2CnhkkfkXpzTXi73x/NGMT6WWdbJ7
+/CHwx9lfDFcYsq+5SwIDAQAB
+-----END PUBLIC KEY-----
diff --git a/tests/auto/network/ssl/qsslcertificate/certificates/gencertificates.sh b/tests/auto/network/ssl/qsslcertificate/certificates/gencertificates.sh
new file mode 100755
index 0000000000..0bac191326
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/certificates/gencertificates.sh
@@ -0,0 +1,104 @@
+#!/bin/sh
+#############################################################################
+##
+## Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+## All rights reserved.
+## Contact: Nokia Corporation (qt-info@nokia.com)
+##
+## This file is the build configuration utility of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## GNU Lesser General Public License Usage
+## This file may be used under the terms of the GNU Lesser General Public
+## License version 2.1 as published by the Free Software Foundation and
+## appearing in the file LICENSE.LGPL included in the packaging of this
+## file. Please review the following information to ensure the GNU Lesser
+## General Public License version 2.1 requirements will be met:
+## http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+##
+## In addition, as a special exception, Nokia gives you certain additional
+## rights. These rights are described in the Nokia Qt LGPL Exception
+## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU General
+## Public License version 3.0 as published by the Free Software Foundation
+## and appearing in the file LICENSE.GPL included in the packaging of this
+## file. Please review the following information to ensure the GNU General
+## Public License version 3.0 requirements will be met:
+## http://www.gnu.org/copyleft/gpl.html.
+##
+## Other Usage
+## Alternatively, this file may be used in accordance with the terms and
+## conditions contained in a signed written agreement between you and Nokia.
+##
+##
+##
+##
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+# This script generates digital certificates of different types.
+
+#--- Certificates ---------------------------------------------------------------------------
+echo -e "\ngenerating 1024-bit RSA private key to PEM file ..."
+openssl genrsa -out rsa-pri-1024.pem 1024
+
+echo -e "\ngenerating the corresponding public key to PEM and DER file ..."
+openssl rsa -in rsa-pri-1024.pem -pubout -out rsa-pub-1024.pem
+openssl rsa -in rsa-pri-1024.pem -pubout -out rsa-pub-1024.der -outform der
+
+echo -e "\ngenerating certificate signing request (CSR) ..."
+openssl req -out req.pem -new -key rsa-pri-1024.pem -subj "/CN=name\/with\/slashes/C=NO"
+
+echo -e "\n generating a self-signed certifificate to PEM file ..."
+openssl x509 -req -in req.pem -out cert-ss.pem -signkey rsa-pri-1024.pem
+
+echo -e "\n generating a self-signed certifificate to DER file ..."
+openssl x509 -req -in req.pem -out cert-ss.der -signkey rsa-pri-1024.pem -outform der
+
+echo -e "\n generating a certifificate signed by a dummy CA to PEM file ..."
+openssl x509 -req -in req.pem -out cert.pem -CA ca-cert.pem -set_serial 17
+
+echo -e "\n generating a certifificate signed by a dummy CA to DER file ..."
+openssl x509 -req -in req.pem -out cert.der -CA ca-cert.pem -set_serial 17 -outform der
+
+#--- Public keys --------------------------------------------------------------------------------
+echo -e "\n associate public keys with all certificates ..."
+# Note: For now, there is only one public key (encoded in both PEM and DER), but that could change.
+/bin/cp rsa-pub-1024.pem cert-ss.pem.pubkey
+/bin/cp rsa-pub-1024.der cert-ss.der.pubkey
+/bin/cp rsa-pub-1024.pem cert.pem.pubkey
+/bin/cp rsa-pub-1024.der cert.der.pubkey
+
+#--- Digests --------------------------------------------------------------------------------
+echo -e "\n generating md5 and sha1 digests of all certificates ..."
+for digest in md5 sha1
+do
+ openssl x509 -in ca-cert.pem -noout -fingerprint -$digest > ca-cert.pem.digest-$digest
+ openssl x509 -in cert-ss.pem -noout -fingerprint -$digest > cert-ss.pem.digest-$digest
+ openssl x509 -in cert.pem -noout -fingerprint -$digest > cert.pem.digest-$digest
+done
+
+#--- Subjet Alternative Name extension ----------------------------------------------------
+echo -e "\n generating self signed root cert. with Subject Alternative Name extension (X509v3) ..."
+outname=cert-ss-san.pem
+openssl req -out req-san.pem -new -key rsa-pri-1024.pem -subj "/CN=Johnny GuitarC=NO"
+openssl req -x509 -in req-san.pem -out $outname -key rsa-pri-1024.pem \
+ -config san.cnf -extensions subj_alt_name
+/bin/cp san.cnf $outname.san
+
+#--- Non-ASCII Subject ---------------------------------------------------------------------
+echo -e "\n generating self signed root cert. with Subject containing UTF-8 characters ..."
+outname=cert-ss-san-utf8.pem
+#subject="/O=HĕĂƲÿ ʍếʈặḻ Récördŝ/OU=㈧A㉁ォBC/CN=Johnny Guitar/C=NO"
+subject=$'/O=H\xc4\x95\xc4\x82\xc6\xb2\xc3\xbf \xca\x8d\xe1\xba\xbf\xca\x88\xe1\xba\xb7\xe1\xb8\xbb R\xc3\xa9c\xc3\xb6rd\xc5\x9d/OU=\xe3\x88\xa7A\xe3\x89\x81\xef\xbd\xabBC/CN=Johnny Guitar/C=NO'
+openssl req -out req-san.pem -new -key rsa-pri-1024.pem -utf8 -subj "$subject"
+openssl req -x509 -in req-san.pem -out $outname -key rsa-pri-1024.pem \
+ -config san.cnf -extensions subj_alt_name -nameopt multiline,utf8,-esc_msb
+/bin/cp san.cnf $outname.san
+
+echo -e "\n cleaning up ..."
+/bin/rm rsa-pri-1024.pem rsa-pub-1024.* req*.pem
diff --git a/tests/auto/network/ssl/qsslcertificate/certificates/san.cnf b/tests/auto/network/ssl/qsslcertificate/certificates/san.cnf
new file mode 100644
index 0000000000..f46a637da4
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/certificates/san.cnf
@@ -0,0 +1,5 @@
+[subj_alt_name]
+subjectAltName=\
+ email:arne@foobar.org,\
+ DNS:www.foobar.org,\
+ email:bjarne@foobar.org
diff --git a/tests/auto/network/ssl/qsslcertificate/more-certificates/badguy-nul-cn.crt b/tests/auto/network/ssl/qsslcertificate/more-certificates/badguy-nul-cn.crt
new file mode 100644
index 0000000000..b899733bbd
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/more-certificates/badguy-nul-cn.crt
@@ -0,0 +1,81 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=GB, ST=Berkshire, L=Newbury, O=My Company Ltd, OU=CA, CN=NULL-friendly CA
+ Validity
+ Not Before: Aug 4 07:33:43 2009 GMT
+ Not After : Aug 2 07:33:43 2019 GMT
+ Subject: CN=www.bank.com\x00.badguy.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (2048 bit)
+ Modulus (2048 bit):
+ 00:cd:26:70:96:a9:a6:5d:3e:9c:ed:0f:08:15:5a:
+ 7c:17:25:68:68:af:13:b9:ad:41:fa:12:54:e2:84:
+ 72:7d:58:d1:e2:40:42:c1:59:ed:05:3d:aa:10:53:
+ 70:00:88:3a:77:a0:c0:56:9e:ac:7d:21:2a:71:44:
+ 51:08:bc:17:07:da:a8:a3:76:dc:51:bc:1b:8a:f6:
+ 02:1a:55:bf:46:b4:44:6b:27:5e:be:e5:17:8b:56:
+ b2:c6:82:36:11:83:a8:bf:f7:2f:0d:17:f6:cd:47:
+ b5:6f:2b:a6:41:b6:8d:33:5f:ea:ea:8b:b1:1a:e2:
+ 99:38:ff:59:5b:0a:a1:71:13:ca:37:3f:b9:b0:1e:
+ 91:9a:c8:93:35:0c:4a:e0:9d:f4:d2:61:c7:4e:5b:
+ 41:0a:7c:31:54:99:db:f5:65:ce:80:d3:c2:02:37:
+ 64:fd:54:12:7b:ea:ac:85:59:5c:17:e1:2e:f6:d0:
+ a8:f2:d0:2e:94:59:2f:c2:a6:5f:da:07:de:7b:2e:
+ 14:07:ed:e4:27:24:37:9d:09:2e:b1:f9:5a:48:b9:
+ 80:24:43:e6:cb:c7:6e:35:df:d5:69:34:ff:e6:d6:
+ 9e:e8:76:66:6e:5f:59:01:3c:96:3b:ec:72:0b:3c:
+ 1e:95:0f:ce:68:13:9c:22:dd:1b:b5:44:28:50:4a:
+ 05:7f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 33:15:24:BE:DA:66:3A:06:8B:D9:27:34:3A:AF:62:40:E4:95:66:5D
+ X509v3 Authority Key Identifier:
+ keyid:0A:69:39:5F:9D:30:04:18:08:2E:02:0E:E6:EA:9D:B2:26:F6:E2:6A
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 32:65:23:1f:c8:d9:53:84:82:d0:0a:eb:14:51:24:03:bc:6c:
+ 1b:2a:5a:fe:1b:f0:e8:69:0c:2b:19:86:cf:7f:32:76:d8:2b:
+ d2:cf:8b:c4:d1:b6:5b:9c:60:a3:99:2e:92:72:06:ce:de:8b:
+ d2:a2:d2:89:7c:13:a9:0b:4e:be:12:09:e5:d6:28:3a:ac:a7:
+ 26:56:94:7f:13:ee:64:7d:de:94:60:75:c1:bc:55:97:d4:aa:
+ 13:8e:02:d8:b0:b0:70:53:ae:18:53:ce:aa:b2:2c:85:3e:e3:
+ f3:e1:26:f3:fa:5c:ee:f8:7b:0b:c6:39:b5:04:33:5e:ae:b8:
+ 5e:0e:66:cc:a8:c0:6a:0d:ec:60:c1:c5:d9:39:ea:bd:1b:8f:
+ 1c:7d:16:38:b1:e8:c8:37:01:aa:4b:99:df:e4:0f:10:be:61:
+ ee:9a:cf:cd:27:05:46:00:60:d8:6a:74:08:32:3c:8b:90:01:
+ 6a:07:33:0c:6c:90:db:ea:fb:6a:17:1a:76:bb:73:14:27:e1:
+ a4:7e:d5:dd:30:b1:5d:f2:0e:aa:d4:b2:d5:4c:f6:4f:91:2a:
+ 07:f4:37:c1:cf:48:19:c5:fe:7e:92:96:a8:df:50:6a:31:92:
+ a3:b1:14:fe:41:cc:49:62:98:4d:ea:c5:ba:05:2d:49:c3:22:
+ 72:ef:41:09
+-----BEGIN CERTIFICATE-----
+MIIDjTCCAnWgAwIBAgIBATANBgkqhkiG9w0BAQUFADB0MQswCQYDVQQGEwJHQjES
+MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5N
+eSBDb21wYW55IEx0ZDELMAkGA1UECxMCQ0ExGTAXBgNVBAMTEE5VTEwtZnJpZW5k
+bHkgQ0EwHhcNMDkwODA0MDczMzQzWhcNMTkwODAyMDczMzQzWjAjMSEwHwYDVQQD
+Exh3d3cuYmFuay5jb20ALmJhZGd1eS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQDNJnCWqaZdPpztDwgVWnwXJWhorxO5rUH6ElTihHJ9WNHiQELB
+We0FPaoQU3AAiDp3oMBWnqx9ISpxRFEIvBcH2qijdtxRvBuK9gIaVb9GtERrJ16+
+5ReLVrLGgjYRg6i/9y8NF/bNR7VvK6ZBto0zX+rqi7Ea4pk4/1lbCqFxE8o3P7mw
+HpGayJM1DErgnfTSYcdOW0EKfDFUmdv1Zc6A08ICN2T9VBJ76qyFWVwX4S720Kjy
+0C6UWS/Cpl/aB957LhQH7eQnJDedCS6x+VpIuYAkQ+bLx24139VpNP/m1p7odmZu
+X1kBPJY77HILPB6VD85oE5wi3Ru1RChQSgV/AgMBAAGjezB5MAkGA1UdEwQCMAAw
+LAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlMB0G
+A1UdDgQWBBQzFSS+2mY6BovZJzQ6r2JA5JVmXTAfBgNVHSMEGDAWgBQKaTlfnTAE
+GAguAg7m6p2yJvbiajANBgkqhkiG9w0BAQUFAAOCAQEAMmUjH8jZU4SC0ArrFFEk
+A7xsGypa/hvw6GkMKxmGz38ydtgr0s+LxNG2W5xgo5kuknIGzt6L0qLSiXwTqQtO
+vhIJ5dYoOqynJlaUfxPuZH3elGB1wbxVl9SqE44C2LCwcFOuGFPOqrIshT7j8+Em
+8/pc7vh7C8Y5tQQzXq64Xg5mzKjAag3sYMHF2TnqvRuPHH0WOLHoyDcBqkuZ3+QP
+EL5h7prPzScFRgBg2Gp0CDI8i5ABagczDGyQ2+r7ahcadrtzFCfhpH7V3TCxXfIO
+qtSy1Uz2T5EqB/Q3wc9IGcX+fpKWqN9QajGSo7EU/kHMSWKYTerFugUtScMicu9B
+CQ==
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/more-certificates/badguy-nul-san.crt b/tests/auto/network/ssl/qsslcertificate/more-certificates/badguy-nul-san.crt
new file mode 100644
index 0000000000..d897c3915e
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/more-certificates/badguy-nul-san.crt
@@ -0,0 +1,83 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 0 (0x0)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=GB, ST=Berkshire, L=Newbury, O=My Company Ltd, OU=CA, CN=NULL-friendly CA
+ Validity
+ Not Before: Aug 4 06:53:05 2009 GMT
+ Not After : Aug 2 06:53:05 2019 GMT
+ Subject: CN=www.badguy.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (2048 bit)
+ Modulus (2048 bit):
+ 00:cd:26:70:96:a9:a6:5d:3e:9c:ed:0f:08:15:5a:
+ 7c:17:25:68:68:af:13:b9:ad:41:fa:12:54:e2:84:
+ 72:7d:58:d1:e2:40:42:c1:59:ed:05:3d:aa:10:53:
+ 70:00:88:3a:77:a0:c0:56:9e:ac:7d:21:2a:71:44:
+ 51:08:bc:17:07:da:a8:a3:76:dc:51:bc:1b:8a:f6:
+ 02:1a:55:bf:46:b4:44:6b:27:5e:be:e5:17:8b:56:
+ b2:c6:82:36:11:83:a8:bf:f7:2f:0d:17:f6:cd:47:
+ b5:6f:2b:a6:41:b6:8d:33:5f:ea:ea:8b:b1:1a:e2:
+ 99:38:ff:59:5b:0a:a1:71:13:ca:37:3f:b9:b0:1e:
+ 91:9a:c8:93:35:0c:4a:e0:9d:f4:d2:61:c7:4e:5b:
+ 41:0a:7c:31:54:99:db:f5:65:ce:80:d3:c2:02:37:
+ 64:fd:54:12:7b:ea:ac:85:59:5c:17:e1:2e:f6:d0:
+ a8:f2:d0:2e:94:59:2f:c2:a6:5f:da:07:de:7b:2e:
+ 14:07:ed:e4:27:24:37:9d:09:2e:b1:f9:5a:48:b9:
+ 80:24:43:e6:cb:c7:6e:35:df:d5:69:34:ff:e6:d6:
+ 9e:e8:76:66:6e:5f:59:01:3c:96:3b:ec:72:0b:3c:
+ 1e:95:0f:ce:68:13:9c:22:dd:1b:b5:44:28:50:4a:
+ 05:7f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 33:15:24:BE:DA:66:3A:06:8B:D9:27:34:3A:AF:62:40:E4:95:66:5D
+ X509v3 Authority Key Identifier:
+ keyid:0A:69:39:5F:9D:30:04:18:08:2E:02:0E:E6:EA:9D:B2:26:F6:E2:6A
+
+ X509v3 Subject Alternative Name:
+ DNS:www.bank.com
+ Signature Algorithm: sha1WithRSAEncryption
+ 27:6e:7d:b3:a9:86:52:57:6a:a0:c6:30:6c:1e:94:09:a7:6f:
+ ad:fe:11:9f:be:32:8d:01:7b:8b:94:66:d7:7c:b6:b1:90:fc:
+ e4:f5:b6:32:bc:6c:71:23:b1:18:88:d6:47:bc:da:07:c7:5e:
+ 46:71:3a:e6:40:6e:c1:7f:1d:56:96:70:65:d8:51:a9:dc:9e:
+ a5:06:00:98:e7:1e:10:bc:82:ba:00:e5:4e:a2:0f:3e:ec:8a:
+ dd:6f:c6:c9:c1:ec:ed:6d:7c:31:3e:66:87:47:a1:8b:15:3c:
+ 21:7e:ec:21:78:3d:21:70:72:ba:70:c3:64:f8:1d:4f:d9:d0:
+ 27:3c:3e:7e:a2:59:ae:be:9a:d3:00:44:a7:72:3a:e3:3f:c8:
+ 9b:c5:8f:b1:94:fe:00:0f:6e:b8:14:88:f1:03:50:91:51:af:
+ f0:1e:f7:b8:5a:a4:57:35:2d:f1:ad:c8:ae:dd:29:61:14:7d:
+ ea:d1:34:80:5c:1b:fd:eb:43:dc:21:6d:c6:44:f9:3b:54:76:
+ c4:91:5b:ac:a4:8e:72:e7:d8:24:ff:a7:5a:c0:ef:27:c3:d7:
+ e4:f9:7f:55:8d:0d:30:ec:a2:d9:6d:c8:76:f4:be:94:3d:12:
+ 32:4a:91:4f:db:c3:e7:76:07:5a:12:97:18:b7:15:00:98:59:
+ 21:89:3e:35
+-----BEGIN CERTIFICATE-----
+MIIDrTCCApWgAwIBAgIBADANBgkqhkiG9w0BAQUFADB0MQswCQYDVQQGEwJHQjES
+MBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5N
+eSBDb21wYW55IEx0ZDELMAkGA1UECxMCQ0ExGTAXBgNVBAMTEE5VTEwtZnJpZW5k
+bHkgQ0EwHhcNMDkwODA0MDY1MzA1WhcNMTkwODAyMDY1MzA1WjAZMRcwFQYDVQQD
+Ew53d3cuYmFkZ3V5LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AM0mcJappl0+nO0PCBVafBclaGivE7mtQfoSVOKEcn1Y0eJAQsFZ7QU9qhBTcACI
+OnegwFaerH0hKnFEUQi8FwfaqKN23FG8G4r2AhpVv0a0RGsnXr7lF4tWssaCNhGD
+qL/3Lw0X9s1HtW8rpkG2jTNf6uqLsRrimTj/WVsKoXETyjc/ubAekZrIkzUMSuCd
+9NJhx05bQQp8MVSZ2/VlzoDTwgI3ZP1UEnvqrIVZXBfhLvbQqPLQLpRZL8KmX9oH
+3nsuFAft5CckN50JLrH5Wki5gCRD5svHbjXf1Wk0/+bWnuh2Zm5fWQE8ljvscgs8
+HpUPzmgTnCLdG7VEKFBKBX8CAwEAAaOBpDCBoTAJBgNVHRMEAjAAMCwGCWCGSAGG
++EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQU
+MxUkvtpmOgaL2Sc0Oq9iQOSVZl0wHwYDVR0jBBgwFoAUCmk5X50wBBgILgIO5uqd
+sib24mowJgYDVR0RBB8wHYIbd3d3LmJhbmsuY29tAHd3dy5iYWRndXkuY29tMA0G
+CSqGSIb3DQEBBQUAA4IBAQAnbn2zqYZSV2qgxjBsHpQJp2+t/hGfvjKNAXuLlGbX
+fLaxkPzk9bYyvGxxI7EYiNZHvNoHx15GcTrmQG7Bfx1WlnBl2FGp3J6lBgCY5x4Q
+vIK6AOVOog8+7Irdb8bJweztbXwxPmaHR6GLFTwhfuwheD0hcHK6cMNk+B1P2dAn
+PD5+olmuvprTAESncjrjP8ibxY+xlP4AD264FIjxA1CRUa/wHve4WqRXNS3xrciu
+3SlhFH3q0TSAXBv960PcIW3GRPk7VHbEkVuspI5y59gk/6dawO8nw9fk+X9VjQ0w
+7KLZbch29L6UPRIySpFP28PndgdaEpcYtxUAmFkhiT41
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted-google.com-diginotar.pem b/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted-google.com-diginotar.pem
new file mode 100644
index 0000000000..12bbcae082
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted-google.com-diginotar.pem
@@ -0,0 +1,30 @@
+-----BEGIN CERTIFICATE-----
+MIIFKDCCBBCgAwIBAgIQBeLmpM0J6lTWZbB1/iKiVjANBgkqhkiG9w0BAQUFADBm
+MQswCQYDVQQGEwJOTDESMBAGA1UEChMJRGlnaU5vdGFyMSEwHwYDVQQDExhEaWdp
+Tm90YXIgUHVibGljIENBIDIwMjUxIDAeBgkqhkiG9w0BCQEWEWluZm9AZGlnaW5v
+dGFyLm5sMB4XDTExMDcxMDE5MDYzMFoXDTEzMDcwOTE5MDYzMFowajELMAkGA1UE
+BhMCVVMxEzARBgNVBAoTCkdvb2dsZSBJbmMxFjAUBgNVBAcTDU1vdW50YWluIFZp
+ZXcxFzAVBgNVBAUTDlBLMDAwMjI5MjAwMDAyMRUwEwYDVQQDEwwqLmdvb2dsZS5j
+b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDNbeKubCV0aCxhOiOS
+CSQ/w9HXTYuD5BLKuiqXNw3setdTymeJz2L8aWOHo3nicFNDVwWTgwWomGNr2J6Q
+7g1iINNSW0rR4E1l2szRkcnAY6c6i/Eke93nF4i2hDsnIBveolF5yjpuRm73uQQD
+ulHjA3BFRF/PTi0fw2/Yt+8ieoMuNcMWN6Eou5Gqt5YZkWv176ofeCbsBmMrP87x
+OhhtTDckCapk4VQZG2XrfzZcV6tdzCp5TI8uHdu17cdzXm1imZ8tyvzFeiCEOQN8
+vPNzB/fIr3CJQ5q4uM5aKT3DD5PeVzf4rfJKQNgCTWiIBc9XcWEUuszwAsnmg7e2
+EJRdAgMBAAGjggHMMIIByDA6BggrBgEFBQcBAQQuMCwwKgYIKwYBBQUHMAGGHmh0
+dHA6Ly92YWxpZGF0aW9uLmRpZ2lub3Rhci5ubDAfBgNVHSMEGDAWgBTfM8Cvkv43
+/LbYFhbQ2bGR1fpupTAJBgNVHRMEAjAAMIHGBgNVHSAEgb4wgbswgbgGDmCEEAGH
+aQEBAQIEAQICMIGlMCcGCCsGAQUFBwIBFhtodHRwOi8vd3d3LmRpZ2lub3Rhci5u
+bC9jcHMwegYIKwYBBQUHAgIwbhpsQ29uZGl0aW9ucywgYXMgbWVudGlvbmVkIG9u
+IG91ciB3ZWJzaXRlICh3d3cuZGlnaW5vdGFyLm5sKSwgYXJlIGFwcGxpY2FibGUg
+dG8gYWxsIG91ciBwcm9kdWN0cyBhbmQgc2VydmljZXMuMEkGA1UdHwRCMEAwPqA8
+oDqGOGh0dHA6Ly9zZXJ2aWNlLmRpZ2lub3Rhci5ubC9jcmwvcHVibGljMjAyNS9s
+YXRlc3RDUkwuY3JsMA4GA1UdDwEB/wQEAwIEsDAbBgNVHREEFDASgRBhZG1pbkBn
+b29nbGUuY29tMB0GA1UdDgQWBBQHSn0WJzIo0eMBMQUNsMqN6eF/7TANBgkqhkiG
+9w0BAQUFAAOCAQEAAs5dL7N9wzRJkI4Aq4lC5t8j5ZadqnqUcgYLADzSv4ExytNH
+UY2nH6iVTihC0UPSsILWraoeApdT7Rphz/8DLQEBRGdeKWAptNM3EbiXtQaZT2uB
+pidL8UoafX0kch3f71Y1scpBEjvu5ZZLnjg0A8AL0tnsereOVdDpU98bKqdbbrnM
+FRmBlSf7xdaNca6JJHeEpga4E9Ty683CmccrSGXdU2tTCuHEJww+iOAUtPIZcsum
+U7/eYeY1pMyGLyIjbNgRY7nDzRwvM/BsbL9eh4/mSQj/4nncqJd22sVQpCggQiVK
+baB2sVGcVNBkK55bT8gPqnx8JypubyUvayzZGg==
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted1.pem b/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted1.pem
new file mode 100644
index 0000000000..7fc0a054c0
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted1.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDDzCCAnigAwIBAgIQBH7L6fylX3vQnq424QyuHjANBgkqhkiG9w0BAQUFADBf
+MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRgwFgYDVQQDEw9tYWlsLmdvb2dsZS5jb20w
+HhcNMTEwODMwMTAxOTI2WhcNMjEwODI3MTAxOTI2WjBfMQswCQYDVQQGEwJBVTET
+MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
+dHkgTHRkMRgwFgYDVQQDEw9tYWlsLmdvb2dsZS5jb20wgZ8wDQYJKoZIhvcNAQEB
+BQADgY0AMIGJAoGBANOvJQGm9vyX8f61SP1XDp23sEDS2SAsDNIxdeONmFthfQRh
+EBlJMNDByegnImZPMN4tA2T2iKcvdkxyQhC9vnQ+HEqJxxu0EhOwO+UdsSII7Lns
+yQZVj2QAoTvC0+MFHPo+wl39JEe3ZytNwQZLjfZSLdS/j0cAyoTkFNconK0bAgMB
+AAGjgcswgcgwHQYDVR0OBBYEFGFxxhfk1fvT8zPfLKPE0YYp9HZEMIGYBgNVHSME
+gZAwgY2AFGFxxhfk1fvT8zPfLKPE0YYp9HZEoWOkYTBfMQswCQYDVQQGEwJBVTET
+MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
+dHkgTHRkMRgwFgYDVQQDEw9tYWlsLmdvb2dsZS5jb22CEAR+y+n8pV970J6uNuEM
+rh4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQAldVSTJ4lNG9Qxx2GG
+/y/ccH/BBYkpPXBklKP/U528Zk48jypWsbnZ07rQrPIlSXYQHffdNH3JsEiF/el9
+bIu+6tGJzmjqvtl5fD5S+yBvI3ySx3Fz6lWmUlqT6UY1X8Oob2PsR6u6mfT8Q1da
+d02x97EUSiAzYvzxndqD6g8R1w==
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted2.pem b/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted2.pem
new file mode 100644
index 0000000000..3c8489fbcd
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted2.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDDjCCAnegAwIBAgIRAPXIavNhYvE6ZPVPbclYfAYwDQYJKoZIhvcNAQEFBQAw
+XjELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGElu
+dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEXMBUGA1UEAxMOd3d3Lmdvb2dsZS5jb20w
+HhcNMTEwODMwMTAxOTUxWhcNMjEwODI3MTAxOTUxWjBeMQswCQYDVQQGEwJBVTET
+MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
+dHkgTHRkMRcwFQYDVQQDEw53d3cuZ29vZ2xlLmNvbTCBnzANBgkqhkiG9w0BAQEF
+AAOBjQAwgYkCgYEAriNo6jkVPi+gyynL2YiPBqDsBa4MuM4rQwM7vcHDRO9GizKi
+6gV7/loaqvr7zqKnHmoARP6OqxDMMEWfZ4QGJjToVKS6srE7dPJEh1lRzK+bsl02
+xGCP/RKJqnZcW1oUpFUceRBQ8TWynZ1L7cE/YUlOhqXnMO9aPibqbWj8AGcCAwEA
+AaOByzCByDAdBgNVHQ4EFgQUo/E6UVU6oRgxQF8yftx0/9dvzMgwgZgGA1UdIwSB
+kDCBjYAUo/E6UVU6oRgxQF8yftx0/9dvzMihYqRgMF4xCzAJBgNVBAYTAkFVMRMw
+EQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0
+eSBMdGQxFzAVBgNVBAMTDnd3dy5nb29nbGUuY29tghEA9chq82Fi8Tpk9U9tyVh8
+BjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAESHOPB9eAsTKkO4lY8d
+EKr2XrRqUkk5KqMFraAHWRekJFwl0R39Q6MDjRHr6NpPJkSKuBPppkr9nk6WDfpt
+TG+oN3Yb1rFmJv6eZw8ud9btoquc8jAtaQnihbjFPEP9cCLBw3Gz1C/JBjDw1tgK
+zXKNU+jMZYk7c5Z64DocggBH
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted3.pem b/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted3.pem
new file mode 100644
index 0000000000..fa458cca36
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted3.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDETCCAnqgAwIBAgIRANdVj9r18RBbshMoK3B3KaMwDQYJKoZIhvcNAQEFBQAw
+XzELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGElu
+dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEYMBYGA1UEAxMPbG9naW4ueWFob28uY29t
+MB4XDTExMDgzMDEwMjAzNloXDTIxMDgyNzEwMjAzNlowXzELMAkGA1UEBhMCQVUx
+EzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMg
+UHR5IEx0ZDEYMBYGA1UEAxMPbG9naW4ueWFob28uY29tMIGfMA0GCSqGSIb3DQEB
+AQUAA4GNADCBiQKBgQC3TVwiPfNClgadKYuX50szBlIaVWDd+UFHsakbGk0bgqlu
+YKgC/cmbjgOyrmsEC2HbJISceTz9CK6mCewEgGFWuq6gjYi4UnSFk1o6h6WJV86A
+tLpeVti7lN9/04IW7XHyxuhvS71V+JWlqfu3zboyaVoMIlHDrPFtRiAh7vTTjQID
+AQABo4HMMIHJMB0GA1UdDgQWBBQrVExlI4rixsrub6IMDDsLPNB4ezCBmQYDVR0j
+BIGRMIGOgBQrVExlI4rixsrub6IMDDsLPNB4e6FjpGEwXzELMAkGA1UEBhMCQVUx
+EzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMg
+UHR5IEx0ZDEYMBYGA1UEAxMPbG9naW4ueWFob28uY29tghEA11WP2vXxEFuyEygr
+cHcpozAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAFB5SF2ujZzH9KMj
+m4ZDTsyy94/YQZdwgLncKUYTxmZe4BdX+42j799pCG+UeQGwqz9hU/soPgibAvGT
+1KCEGQ6qtWSqKJYmC8VKenYvvEFIySj5cbSFmId5aNwhjl8AYoLuM0E+2FRVJQ6a
+pWyzYUIOqhsCkt9hEPsDVP4hIhP+
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted4.pem b/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted4.pem
new file mode 100644
index 0000000000..53761bb36a
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted4.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDDzCCAnigAwIBAgIQOSpDTw4H3x+KowXeNODCKTANBgkqhkiG9w0BAQUFADBf
+MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRgwFgYDVQQDEw9sb2dpbi55YWhvby5jb20w
+HhcNMTEwODMwMTAyMTE5WhcNMjEwODI3MTAyMTE5WjBfMQswCQYDVQQGEwJBVTET
+MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
+dHkgTHRkMRgwFgYDVQQDEw9sb2dpbi55YWhvby5jb20wgZ8wDQYJKoZIhvcNAQEB
+BQADgY0AMIGJAoGBAML+Z5hpY4VfSeTPbMCGaqe5shwcw3yW/egYY6cXcfxtUkjs
+Eai48hP/sqtQeFwi3puJ7HO2iGUX72/UnO0t9qwEGtGOHS1qqAYdTcncY5pTpO9L
+e4Tn6CkPwFE4VNXVU96xPlUjP/KBZ43VH6gW3M1xDI0DmNh2QUXHN5ErQE8nAgMB
+AAGjgcswgcgwHQYDVR0OBBYEFI+gG6PT7vQtUVn2xf+wCYZV5Ht8MIGYBgNVHSME
+gZAwgY2AFI+gG6PT7vQtUVn2xf+wCYZV5Ht8oWOkYTBfMQswCQYDVQQGEwJBVTET
+MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
+dHkgTHRkMRgwFgYDVQQDEw9sb2dpbi55YWhvby5jb22CEDkqQ08OB98fiqMF3jTg
+wikwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQA3eZG/dOXrL7YBPCA8
+joDGfhra98T1iCpul4/L/L4dt/9+QVAu+agbZmHWLYzuAvuB1zj8go0BLIE7b4ap
+HPLFYXV3iAWjIRhNEix4FWohlds1B+IwpvWdsl3Op1pZfHQ0yq8wFGawdQTAKUII
+lLu1cd6E8B6pCfWwSr+9h6gnTg==
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted5.pem b/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted5.pem
new file mode 100644
index 0000000000..81211ee694
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted5.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDDzCCAnigAwIBAgIQPnXO1GtpMCEhiDCuhqgqcTANBgkqhkiG9w0BAQUFADBf
+MQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50
+ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMRgwFgYDVQQDEw9sb2dpbi55YWhvby5jb20w
+HhcNMTEwODMwMTAyMTQ4WhcNMjEwODI3MTAyMTQ4WjBfMQswCQYDVQQGEwJBVTET
+MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
+dHkgTHRkMRgwFgYDVQQDEw9sb2dpbi55YWhvby5jb20wgZ8wDQYJKoZIhvcNAQEB
+BQADgY0AMIGJAoGBAL5IeUbbQ7HxCBLQaOASV2HyI1tRwPm/7JNsRfh5ipM1sCWE
+xnPoqFznX6ZUKi8d61/EIycwUd+FvOp9zoRxDlngoRdhqMCTTG3JfxNf6ZXJPCYd
+qPjOKAkMwyG8bbhGCsoCws9b2rpN9536qVXc2QR39F9/ZE5t73oKtEd1fyNnAgMB
+AAGjgcswgcgwHQYDVR0OBBYEFNXCkfGdW3WYzBBqB2jWppl6sL99MIGYBgNVHSME
+gZAwgY2AFNXCkfGdW3WYzBBqB2jWppl6sL99oWOkYTBfMQswCQYDVQQGEwJBVTET
+MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
+dHkgTHRkMRgwFgYDVQQDEw9sb2dpbi55YWhvby5jb22CED51ztRraTAhIYgwroao
+KnEwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOBgQCOeih7N7fmkqECWZD/
+bYsFLtbKOwD4YMPIV2wayvaLg2dFwqhBkGml+5ulOh5KTiUh0/nnGmGAU/3K9nt5
+TCMjwMGHm/C5pp7THQriiY8Qw0QVtnFiJGnjblhAbJVIvBJJ42/Qq7T4IzEwqShW
+hO2g1M0MUGiOw4vyXJRGc4dg2w==
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted6.pem b/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted6.pem
new file mode 100644
index 0000000000..4264a678f1
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted6.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDETCCAnqgAwIBAgIRAOkCi5V45BXcGnEKK4gVREcwDQYJKoZIhvcNAQEFBQAw
+XzELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGElu
+dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEYMBYGA1UEAxMPbG9naW4uc2t5cGUuY29t
+MB4XDTExMDgzMDEwMjIxOFoXDTIxMDgyNzEwMjIxOFowXzELMAkGA1UEBhMCQVUx
+EzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMg
+UHR5IEx0ZDEYMBYGA1UEAxMPbG9naW4uc2t5cGUuY29tMIGfMA0GCSqGSIb3DQEB
+AQUAA4GNADCBiQKBgQDAAkuUFRdz1bm95jFsyQRb4PBrly4pJK4f5pSZy99eY8FM
+iZbr7brnkiheN4qeJfS1dv/B/B4kAVoGD2Y0KmpZ5ZZYmm3TxopoP0Yeg6juWNKa
+iFlfKQIvk0GEmD8oGfEqW1+72p040jAuTn+OQx+7VpydqB/RJoY8qK3zEXbB7wID
+AQABo4HMMIHJMB0GA1UdDgQWBBSE9drle8VwSlwYIX5mKaIEvQYX/zCBmQYDVR0j
+BIGRMIGOgBSE9drle8VwSlwYIX5mKaIEvQYX/6FjpGEwXzELMAkGA1UEBhMCQVUx
+EzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMg
+UHR5IEx0ZDEYMBYGA1UEAxMPbG9naW4uc2t5cGUuY29tghEA6QKLlXjkFdwacQor
+iBVERzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBACm4/Q6e001Fg9uu
+ieqHOAxfBafkOsXtgKqTFFdpt9Hbmo9j/BfvrtvfFN5Ph4fV46useGjW79P1IeNK
++KqcaqOKy2q6j1em4j8C5Mx6S4ksZJC25jIPEM7cdxiDGcV505X5mynlu1+WkZAf
+nQhnJpA8o3p462ON4S+GXTfOLfoN
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted7.pem b/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted7.pem
new file mode 100644
index 0000000000..03ab7d46b0
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted7.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDGjCCAoOgAwIBAgIRAJI51TSPQNFpWnRUcOHyP0MwDQYJKoZIhvcNAQEFBQAw
+YjELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGElu
+dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEbMBkGA1UEAxMSYWRkb25zLm1vemlsbGEu
+b3JnMB4XDTExMDgzMDEwMjIzOVoXDTIxMDgyNzEwMjIzOVowYjELMAkGA1UEBhMC
+QVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdp
+dHMgUHR5IEx0ZDEbMBkGA1UEAxMSYWRkb25zLm1vemlsbGEub3JnMIGfMA0GCSqG
+SIb3DQEBAQUAA4GNADCBiQKBgQC9Yo3DJvs+vewelK5qoK+0Xn4zeRIQ/wJCrQBg
+5tNXja+NZsHb0/enlwAZ3dAwCfI0G12mTowgSuZyDX7oN2+G+k6Q5LPnGhj1E5s5
+OJ+ZYsAjTdU0SCAPquva55+jyhqo5w/B5Il7w84mppUrAZgqEGhYkhXeDOULe1Vm
+4iLMQwIDAQABo4HPMIHMMB0GA1UdDgQWBBSb8lAIgOnUitVOuZIx3s+5MN1sBzCB
+nAYDVR0jBIGUMIGRgBSb8lAIgOnUitVOuZIx3s+5MN1sB6FmpGQwYjELMAkGA1UE
+BhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdp
+ZGdpdHMgUHR5IEx0ZDEbMBkGA1UEAxMSYWRkb25zLm1vemlsbGEub3JnghEAkjnV
+NI9A0WladFRw4fI/QzAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAFpg
+tcp6ynOZ/hwr2axTYK+4rtXmTUJdsg7NUHhXSwGANAuYuc7PYwqtmz3B2W90t3TA
+D3pNMRBEXrBXufC0p9vu/hQgb+mdQ7DG6j1Gkkpq4Sq/Puv1bO96KpAufmevnWWB
+48kzCgAdfk/N04k7kdPHCp5MjjgmY3kGdsg+jroj
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted8.pem b/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted8.pem
new file mode 100644
index 0000000000..acef06ffb0
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted8.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDDjCCAnegAwIBAgIRALC3Ez7Qlvm1b66RyHS9OsAwDQYJKoZIhvcNAQEFBQAw
+XjELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGElu
+dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEXMBUGA1UEAxMObG9naW4ubGl2ZS5jb20w
+HhcNMTEwODMwMTAyMzA0WhcNMjEwODI3MTAyMzA0WjBeMQswCQYDVQQGEwJBVTET
+MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
+dHkgTHRkMRcwFQYDVQQDEw5sb2dpbi5saXZlLmNvbTCBnzANBgkqhkiG9w0BAQEF
+AAOBjQAwgYkCgYEA5JK77+1zFatj8xeItZaDW5XaU+ssc5jq2Ww4ANaxJi+wdRVU
+qVLauEJPKEXC51fuYHa7U8yoSTgJZA7JL07cdSxgsVj8RR4Uf5k4Jf5Vdz5w8+TT
+W33I3zurA2xB+wfup2VPmS8Alg07w6POrzlQYgtcUcELZhjcdypk96NOdPECAwEA
+AaOByzCByDAdBgNVHQ4EFgQUTWM20msyZUcNEYOyNbgevBPIoF8wgZgGA1UdIwSB
+kDCBjYAUTWM20msyZUcNEYOyNbgevBPIoF+hYqRgMF4xCzAJBgNVBAYTAkFVMRMw
+EQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0
+eSBMdGQxFzAVBgNVBAMTDmxvZ2luLmxpdmUuY29tghEAsLcTPtCW+bVvrpHIdL06
+wDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBACQqnu1KywflnNiqIU01
+95z/qjmZTvSWafM/HLOFUg8ls7g32l5gCCrsc8ypiCff+S3+9teYQOII7oW3hzw4
+BH10m0LTRxGig5U9XVkH4076SALkPoky1z+onMmLk7AE96kSJ+rq30VvcSSl9BaW
+DwcQGIhCZANgZrNW9AJ+cweQ
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted9.pem b/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted9.pem
new file mode 100644
index 0000000000..cc99b08e5f
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/more-certificates/blacklisted9.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDDjCCAnegAwIBAgIRANjzX063hystqwaS4xU4L7AwDQYJKoZIhvcNAQEFBQAw
+XjELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGElu
+dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEXMBUGA1UEAxMOZ2xvYmFsIHRydXN0ZWUw
+HhcNMTEwODMwMTAyMzI1WhcNMjEwODI3MTAyMzI1WjBeMQswCQYDVQQGEwJBVTET
+MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
+dHkgTHRkMRcwFQYDVQQDEw5nbG9iYWwgdHJ1c3RlZTCBnzANBgkqhkiG9w0BAQEF
+AAOBjQAwgYkCgYEAw0CpZXrd6oI8/PHo8/bnNwB7UA7OKsRFuqKljr9F5lCJAVkT
+zRDlXuTDeXGfQiYhJTF7GRunPRJ7O5SsflwoxktH/F91yFpgxY5DqRZ1ZHdZgW3b
+W0uweBxJv9684ihXY4YR3Yznf0js7YAgVd8a3qhOUODiC/Beb8tmDBNL2c0CAwEA
+AaOByzCByDAdBgNVHQ4EFgQU/rUvQ2rG7pg2muUiLm6V93ZgmGcwgZgGA1UdIwSB
+kDCBjYAU/rUvQ2rG7pg2muUiLm6V93ZgmGehYqRgMF4xCzAJBgNVBAYTAkFVMRMw
+EQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0
+eSBMdGQxFzAVBgNVBAMTDmdsb2JhbCB0cnVzdGVlghEA2PNfTreHKy2rBpLjFTgv
+sDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBALvmmUx47DcUAIsPkI0Y
+DTvcXV6k2JHwdrdlPsrn9A5TLppfxPNrDMiweitr8cMkKEtkm6LRTt2yvDFcMIwy
+/+F5+XO0k9sKde6xHfWvOvndIycj3Lt4tIRW8jUauJENyMa4M57qpqkgkJEmflkI
+/pb9fQZbfg70o9wvbNK0RONo
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/more-certificates/cert-large-expiration-date.pem b/tests/auto/network/ssl/qsslcertificate/more-certificates/cert-large-expiration-date.pem
new file mode 100644
index 0000000000..416dd4da04
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/more-certificates/cert-large-expiration-date.pem
@@ -0,0 +1,15 @@
+-----BEGIN CERTIFICATE-----
+MIICWjCCAcOgAwIBAgIJAM7bMShFxAVAMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
+BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
+aWRnaXRzIFB0eSBMdGQwIBcNMTAwODA0MDk1MzQxWhgPMjA1MTA4MjkwOTUzNDFa
+MEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJ
+bnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJ
+AoGBAM2q22/WNMmn8cC+5EEYGeICySLmp9W6Ay6eKHr0Xxp3X3epETuPfvAuxp7r
+OtkS18EMUegkUj8jw0IMEcbyHKFC/rTCaYOt93CxGBXMIChiMPAsFeYzGa/D6xzA
+kfcRaJRQ+Ek3CDLXPnXfo7xpABXezYcPXAJrgsgBfWrwHdxzAgMBAAGjUDBOMB0G
+A1UdDgQWBBSKbhnnl5uP2X+zuwFP6GovUpUN2TAfBgNVHSMEGDAWgBSKbhnnl5uP
+2X+zuwFP6GovUpUN2TAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAKF0
+jl02liwFfupmzC5oxz2T3IyjEa21fm7QBMQJvQr5OTuX1/C7DAl7g/6/h7BH6JS3
+qpx5rXGet8SZmG8dODL4o3U4xOXnNzch7HtQixWwlx4XnFAXPMHflFX7YC5QQNHq
+I8Y8IW+XjAYWpYJywWMUZIbr1/9y9gn1beYEE3pq
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/more-certificates/cert-large-expiration-date.txt.0.9.8 b/tests/auto/network/ssl/qsslcertificate/more-certificates/cert-large-expiration-date.txt.0.9.8
new file mode 100644
index 0000000000..20500b221f
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/more-certificates/cert-large-expiration-date.txt.0.9.8
@@ -0,0 +1,42 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ ce:db:31:28:45:c4:05:40
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=AU, ST=Some-State, O=Internet Widgits Pty Ltd
+ Validity
+ Not Before: Aug 4 09:53:41 2010 GMT
+ Not After : Aug 29 09:53:41 2051 GMT
+ Subject: C=AU, ST=Some-State, O=Internet Widgits Pty Ltd
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:cd:aa:db:6f:d6:34:c9:a7:f1:c0:be:e4:41:18:
+ 19:e2:02:c9:22:e6:a7:d5:ba:03:2e:9e:28:7a:f4:
+ 5f:1a:77:5f:77:a9:11:3b:8f:7e:f0:2e:c6:9e:eb:
+ 3a:d9:12:d7:c1:0c:51:e8:24:52:3f:23:c3:42:0c:
+ 11:c6:f2:1c:a1:42:fe:b4:c2:69:83:ad:f7:70:b1:
+ 18:15:cc:20:28:62:30:f0:2c:15:e6:33:19:af:c3:
+ eb:1c:c0:91:f7:11:68:94:50:f8:49:37:08:32:d7:
+ 3e:75:df:a3:bc:69:00:15:de:cd:87:0f:5c:02:6b:
+ 82:c8:01:7d:6a:f0:1d:dc:73
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 8A:6E:19:E7:97:9B:8F:D9:7F:B3:BB:01:4F:E8:6A:2F:52:95:0D:D9
+ X509v3 Authority Key Identifier:
+ keyid:8A:6E:19:E7:97:9B:8F:D9:7F:B3:BB:01:4F:E8:6A:2F:52:95:0D:D9
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ a1:74:8e:5d:36:96:2c:05:7e:ea:66:cc:2e:68:c7:3d:93:dc:
+ 8c:a3:11:ad:b5:7e:6e:d0:04:c4:09:bd:0a:f9:39:3b:97:d7:
+ f0:bb:0c:09:7b:83:fe:bf:87:b0:47:e8:94:b7:aa:9c:79:ad:
+ 71:9e:b7:c4:99:98:6f:1d:38:32:f8:a3:75:38:c4:e5:e7:37:
+ 37:21:ec:7b:50:8b:15:b0:97:1e:17:9c:50:17:3c:c1:df:94:
+ 55:fb:60:2e:50:40:d1:ea:23:c6:3c:21:6f:97:8c:06:16:a5:
+ 82:72:c1:63:14:64:86:eb:d7:ff:72:f6:09:f5:6d:e6:04:13:
+ 7a:6a
diff --git a/tests/auto/network/ssl/qsslcertificate/more-certificates/cert-large-expiration-date.txt.1.0.0 b/tests/auto/network/ssl/qsslcertificate/more-certificates/cert-large-expiration-date.txt.1.0.0
new file mode 100644
index 0000000000..b2ccb2751e
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/more-certificates/cert-large-expiration-date.txt.1.0.0
@@ -0,0 +1,42 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ ce:db:31:28:45:c4:05:40
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=AU, ST=Some-State, O=Internet Widgits Pty Ltd
+ Validity
+ Not Before: Aug 4 09:53:41 2010 GMT
+ Not After : Aug 29 09:53:41 2051 GMT
+ Subject: C=AU, ST=Some-State, O=Internet Widgits Pty Ltd
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:cd:aa:db:6f:d6:34:c9:a7:f1:c0:be:e4:41:18:
+ 19:e2:02:c9:22:e6:a7:d5:ba:03:2e:9e:28:7a:f4:
+ 5f:1a:77:5f:77:a9:11:3b:8f:7e:f0:2e:c6:9e:eb:
+ 3a:d9:12:d7:c1:0c:51:e8:24:52:3f:23:c3:42:0c:
+ 11:c6:f2:1c:a1:42:fe:b4:c2:69:83:ad:f7:70:b1:
+ 18:15:cc:20:28:62:30:f0:2c:15:e6:33:19:af:c3:
+ eb:1c:c0:91:f7:11:68:94:50:f8:49:37:08:32:d7:
+ 3e:75:df:a3:bc:69:00:15:de:cd:87:0f:5c:02:6b:
+ 82:c8:01:7d:6a:f0:1d:dc:73
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 8A:6E:19:E7:97:9B:8F:D9:7F:B3:BB:01:4F:E8:6A:2F:52:95:0D:D9
+ X509v3 Authority Key Identifier:
+ keyid:8A:6E:19:E7:97:9B:8F:D9:7F:B3:BB:01:4F:E8:6A:2F:52:95:0D:D9
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ a1:74:8e:5d:36:96:2c:05:7e:ea:66:cc:2e:68:c7:3d:93:dc:
+ 8c:a3:11:ad:b5:7e:6e:d0:04:c4:09:bd:0a:f9:39:3b:97:d7:
+ f0:bb:0c:09:7b:83:fe:bf:87:b0:47:e8:94:b7:aa:9c:79:ad:
+ 71:9e:b7:c4:99:98:6f:1d:38:32:f8:a3:75:38:c4:e5:e7:37:
+ 37:21:ec:7b:50:8b:15:b0:97:1e:17:9c:50:17:3c:c1:df:94:
+ 55:fb:60:2e:50:40:d1:ea:23:c6:3c:21:6f:97:8c:06:16:a5:
+ 82:72:c1:63:14:64:86:eb:d7:ff:72:f6:09:f5:6d:e6:04:13:
+ 7a:6a
diff --git a/tests/auto/network/ssl/qsslcertificate/more-certificates/cert-large-serial-number.pem b/tests/auto/network/ssl/qsslcertificate/more-certificates/cert-large-serial-number.pem
new file mode 100644
index 0000000000..ecb6c35632
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/more-certificates/cert-large-serial-number.pem
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICGjCCAYMCFAECAwQFBgcICRCqu8zd7v8XGBkgMA0GCSqGSIb3DQEBBQUAMEwx
+CzAJBgNVBAYTAkdCMRIwEAYDVQQIEwlCZXJrc2hpcmUxEDAOBgNVBAcTB05ld2J1
+cnkxFzAVBgNVBAoTDk15IENvbXBhbnkgTHRkMB4XDTEwMDYwMTE1MDI0MVoXDTEx
+MDYwMTE1MDI0MVowTDELMAkGA1UEBhMCR0IxEjAQBgNVBAgTCUJlcmtzaGlyZTEQ
+MA4GA1UEBxMHTmV3YnVyeTEXMBUGA1UEChMOTXkgQ29tcGFueSBMdGQwgZ8wDQYJ
+KoZIhvcNAQEBBQADgY0AMIGJAoGBAM2q22/WNMmn8cC+5EEYGeICySLmp9W6Ay6e
+KHr0Xxp3X3epETuPfvAuxp7rOtkS18EMUegkUj8jw0IMEcbyHKFC/rTCaYOt93Cx
+GBXMIChiMPAsFeYzGa/D6xzAkfcRaJRQ+Ek3CDLXPnXfo7xpABXezYcPXAJrgsgB
+fWrwHdxzAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAtlScqSn4IHFLRiQYQdfOgsPi
+wdqD1MPZEniQE0Xp8McZ7kuYbGgdEqzeVgMHqitlzkNNtTz+2u37CbFNXDGCTy5D
+2JCgZxaAWNkh1w+4VB91HfMwEU0MqvAO7SB31FwbKNaB3gVnua++NL1cAkujyRny
+yR3PatYZCfESQ7oZgds=
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/more-certificates/malformed-just-begin-no-newline.pem b/tests/auto/network/ssl/qsslcertificate/more-certificates/malformed-just-begin-no-newline.pem
new file mode 100644
index 0000000000..75f3c32241
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/more-certificates/malformed-just-begin-no-newline.pem
@@ -0,0 +1 @@
+-----BEGIN CERTIFICATE----- \ No newline at end of file
diff --git a/tests/auto/network/ssl/qsslcertificate/more-certificates/malformed-just-begin.pem b/tests/auto/network/ssl/qsslcertificate/more-certificates/malformed-just-begin.pem
new file mode 100644
index 0000000000..a71aecf9af
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/more-certificates/malformed-just-begin.pem
@@ -0,0 +1 @@
+-----BEGIN CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/more-certificates/natwest-banking.pem b/tests/auto/network/ssl/qsslcertificate/more-certificates/natwest-banking.pem
new file mode 100644
index 0000000000..c3e303c770
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/more-certificates/natwest-banking.pem
@@ -0,0 +1,36 @@
+-----BEGIN CERTIFICATE-----
+MIIGTTCCBTWgAwIBAgIQEdaGfQ9bnSLsmQJm4rWlBjANBgkqhkiG9w0BAQUFADCB
+vjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
+ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTswOQYDVQQLEzJUZXJtcyBvZiB1c2Ug
+YXQgaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYSAoYykwNjE4MDYGA1UEAxMv
+VmVyaVNpZ24gQ2xhc3MgMyBFeHRlbmRlZCBWYWxpZGF0aW9uIFNTTCBTR0MgQ0Ew
+HhcNMDkwOTE1MDAwMDAwWhcNMTExMTA5MjM1OTU5WjCCAQAxEzARBgsrBgEEAYI3
+PAIBAxMCR0IxGzAZBgNVBA8TElYxLjAsIENsYXVzZSA1LihiKTERMA8GA1UEBRMI
+U0MwNDU1NTExCzAJBgNVBAYTAkdCMRAwDgYDVQQRFAdFSDMgNlVZMRAwDgYDVQQI
+EwdMb3RoaWFuMRIwEAYDVQQHFAlFZGluYnVyZ2gxFjAUBgNVBAkUDTM0IEZldHRl
+cyBSb3cxLTArBgNVBAoUJFRoZSBSb3lhbCBCYW5rIG9mIFNjb3RsYW5kIEdyb3Vw
+IFBsYzEVMBMGA1UECxQMV2ViIFNlcnZpY2VzMRYwFAYDVQQDFA13d3cubndvbGIu
+Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw4bRz9mxrbicnYun
+uYoobkfDBjmmJKpSDBbcZCsZDWyLsLvoZh2Ez6Ux9GAbf4m5pLoIQnzQORy40NAt
+bNDFhMJV0Iq65ju8qdYaUaWUdrxkLiwrIsiZwUMgcDOwdOvgO4qTev2OjkQg6syj
+J+3HTaRrqekfrV5RvBNZ8vPVXK3cWERykzxwqXHwr9QL/n3wqDn4hCOb11Ic2rUf
+H9TcPvxv7eFFnGL4ZJ3EU83tE/CmOYgz086BUDBKSvOHqHt2QWiPN/tHAgwfHYKj
+eYCMWM21G0rDugeN+urZN+p364kO+VygBxnNIPSr/ZY+4DCdjaKGe8sOJdvI6ip5
+4a1q3QIDAQABo4ICADCCAfwwCQYDVR0TBAIwADAdBgNVHQ4EFgQUX5AjzSTKUsk2
+KfB+nbH+CODuafAwCwYDVR0PBAQDAgWgMD4GA1UdHwQ3MDUwM6AxoC+GLWh0dHA6
+Ly9FVkludGwtY3JsLnZlcmlzaWduLmNvbS9FVkludGwyMDA2LmNybDBEBgNVHSAE
+PTA7MDkGC2CGSAGG+EUBBxcGMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LnZl
+cmlzaWduLmNvbS9ycGEwNAYDVR0lBC0wKwYIKwYBBQUHAwEGCCsGAQUFBwMCBglg
+hkgBhvhCBAEGCisGAQQBgjcKAwMwHwYDVR0jBBgwFoAUTkPIHXbvN1N6T/JYb5Tz
+OOLVvd8wdgYIKwYBBQUHAQEEajBoMCsGCCsGAQUFBzABhh9odHRwOi8vRVZJbnRs
+LW9jc3AudmVyaXNpZ24uY29tMDkGCCsGAQUFBzAChi1odHRwOi8vRVZJbnRsLWFp
+YS52ZXJpc2lnbi5jb20vRVZJbnRsMjAwNi5jZXIwbgYIKwYBBQUHAQwEYjBgoV6g
+XDBaMFgwVhYJaW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUS2u5KJYGDLvQUjibKaxL
+B4shBRgwJhYkaHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nbzEuZ2lmMA0G
+CSqGSIb3DQEBBQUAA4IBAQCT64k2YepUu257B3pA4pjbKr/dmlOztUYS/IAtlJpo
+As+R+T9dohGP+4liqHtlMMSKPRnwmSCj/KucJJ9UnIC89D3bVAP1Drvk5+gTwGZ5
+JkqPQqZsfEaeihmf8iu9stkYSQxMJcr24S4VEiGt2rdHhESq0OUel4SkMhlmSp5P
+sZxqX1HByBJnsF4bcvIY3C4eTrso5awqNgomGhxizJWmK8/sdEcys82SHgSjG4Bp
+05gUpXQrLTqWXDDOg5Uy745Gc8TpgqW1ZfpGg7EkjJX7EhBSKF0/2cNKVYUE9bnO
+VGd7vK10NOhK7Uk9CkDALK+MvIIkxmRBmAFuQ4D+eqNF
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/more-certificates/no-ending-newline.pem b/tests/auto/network/ssl/qsslcertificate/more-certificates/no-ending-newline.pem
new file mode 100644
index 0000000000..f8056c72d0
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/more-certificates/no-ending-newline.pem
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIIB8zCCAVwCAREwDQYJKoZIhvcNAQEFBQAwWzELMAkGA1UEBhMCQVUxEzARBgNV
+BAgTClF1ZWVuc2xhbmQxGjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMRswGQYD
+VQQDExJUZXN0IENBICgxMDI0IGJpdCkwHhcNMDcwNDE3MDc0MDI2WhcNMDcwNTE3
+MDc0MDI2WjApMRowGAYDVQQDExFuYW1lL3dpdGgvc2xhc2hlczELMAkGA1UEBhMC
+Tk8wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOud6QOsME+pWANExxgmL0iT
+1ayg++hTxHsqAYnm/FoMxfUh+NdKkgJn2/GfNppinfPOSI667VqonU+7JBZDTLV5
+CPbZIo9fFQpDJQN6naev4yaxU1VeYFfI7S8c8zYKeGSR+RenNNeLvfH80YxPpZZ1
+snv8IfDH2V8MVxiyr7lLAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAleaU4pgzV6KY
++q9QuXapUYMsC2GiNtDmkG3k+MTHUO8XlE4hqPrIM6rRf7zKQdZ950R2wL9FSnYl
+Qm1Tdv38dCka6ivMBqvRuOt9axH3m0G7nzHL7U3zaCbtEx3yVln+b3yYtiVpTuq0
+3MLrt7tQGAW6ra8ISf6YY1W65/uVXZE=
+-----END CERTIFICATE----- \ No newline at end of file
diff --git a/tests/auto/network/ssl/qsslcertificate/more-certificates/test-cn-two-cns-cert.pem b/tests/auto/network/ssl/qsslcertificate/more-certificates/test-cn-two-cns-cert.pem
new file mode 100644
index 0000000000..08176289d7
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/more-certificates/test-cn-two-cns-cert.pem
@@ -0,0 +1,67 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 10 (0xa)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: CN=Westpoint Certificate Test CA, ST=Lancashire, C=UK/emailAddress=ca@example.com, O=Westpoint Certificate Test Root Certification Authority
+ Validity
+ Not Before: Jul 31 21:01:17 2011 GMT
+ Not After : Jul 28 21:01:17 2021 GMT
+ Subject: CN=www.example.com, CN=www2.example.com, ST=Lancashire, C=UK, O=Some organisation
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:e8:61:96:bd:d0:d2:c6:54:92:15:fe:42:2b:86:
+ 20:dc:74:51:82:c8:b4:5e:5e:c5:3b:01:6e:1e:84:
+ 8d:4a:8c:6f:d8:63:21:a7:74:16:02:62:c3:84:1f:
+ ac:83:00:ad:6d:f8:79:d0:48:19:4a:a4:45:bf:24:
+ 88:db:89:f7:96:80:70:b1:f9:94:46:8d:52:cd:47:
+ 11:86:74:3b:04:c6:d2:08:3b:4d:70:b0:d4:a2:5a:
+ ae:54:43:4e:8c:26:05:77:b4:52:8b:bf:43:26:cd:
+ 6e:b6:04:ca:36:e1:cf:c3:70:52:7b:73:40:1d:1f:
+ 2a:44:b9:fc:d3:be:77:5a:df
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Authority Information Access:
+ OCSP - URI:http://ocsp.example.com:8888/
+
+ Signature Algorithm: sha1WithRSAEncryption
+ a7:ce:f4:72:aa:54:01:d5:a0:ef:fb:54:a5:79:d0:51:87:27:
+ 93:37:d7:a8:92:a0:51:a4:56:a6:93:ea:3b:f4:e2:07:68:29:
+ 2b:59:e6:eb:71:d8:78:0a:b2:e2:df:13:9f:68:f9:6b:d8:42:
+ c6:ff:3b:e1:2e:01:91:9b:eb:90:7f:da:54:7e:5a:47:ba:40:
+ 18:fb:a5:f7:8a:3a:b0:05:37:03:a8:b8:23:61:d4:58:37:97:
+ 87:54:57:62:aa:7f:e6:73:8f:74:f4:3b:57:29:af:bb:f7:bc:
+ 33:72:d4:f3:02:22:44:3e:70:1f:48:59:7d:6e:a0:af:c4:91:
+ 58:4c:99:6b:33:28:36:09:59:c7:71:a7:94:ba:0e:af:87:d2:
+ 47:75:86:c1:ac:2d:ab:89:83:03:a9:97:cb:50:39:c1:66:a3:
+ a2:92:f6:c8:42:05:5b:d3:e4:13:17:84:10:57:8f:3e:ae:d0:
+ 5e:f7:15:54:dd:04:61:2f:d6:d4:25:00:d6:6f:02:bb:b9:9f:
+ ff:ab:d2:a0:32:87:a0:d2:ff:91:29:bf:5d:74:61:d8:86:e5:
+ 89:29:5e:c0:85:b1:05:e1:79:68:50:fa:21:98:cc:26:09:d1:
+ 86:18:4d:2e:84:21:33:d1:ff:b5:bf:78:2d:0b:9e:8c:51:82:
+ 09:9c:03:ec
+-----BEGIN CERTIFICATE-----
+MIIDXjCCAkagAwIBAgIBCjANBgkqhkiG9w0BAQUFADCBqzEmMCQGA1UEAxMdV2Vz
+dHBvaW50IENlcnRpZmljYXRlIFRlc3QgQ0ExEzARBgNVBAgTCkxhbmNhc2hpcmUx
+CzAJBgNVBAYTAlVLMR0wGwYJKoZIhvcNAQkBFg5jYUBleGFtcGxlLmNvbTFAMD4G
+A1UEChM3V2VzdHBvaW50IENlcnRpZmljYXRlIFRlc3QgUm9vdCBDZXJ0aWZpY2F0
+aW9uIEF1dGhvcml0eTAeFw0xMTA3MzEyMTAxMTdaFw0yMTA3MjgyMTAxMTdaMHMx
+GDAWBgNVBAMTD3d3dy5leGFtcGxlLmNvbTEZMBcGA1UEAxMQd3d3Mi5leGFtcGxl
+LmNvbTETMBEGA1UECBMKTGFuY2FzaGlyZTELMAkGA1UEBhMCVUsxGjAYBgNVBAoT
+EVNvbWUgb3JnYW5pc2F0aW9uMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDo
+YZa90NLGVJIV/kIrhiDcdFGCyLReXsU7AW4ehI1KjG/YYyGndBYCYsOEH6yDAK1t
++HnQSBlKpEW/JIjbifeWgHCx+ZRGjVLNRxGGdDsExtIIO01wsNSiWq5UQ06MJgV3
+tFKLv0MmzW62BMo24c/DcFJ7c0AdHypEufzTvnda3wIDAQABo0gwRjAJBgNVHRME
+AjAAMDkGCCsGAQUFBwEBBC0wKzApBggrBgEFBQcwAYYdaHR0cDovL29jc3AuZXhh
+bXBsZS5jb206ODg4OC8wDQYJKoZIhvcNAQEFBQADggEBAKfO9HKqVAHVoO/7VKV5
+0FGHJ5M316iSoFGkVqaT6jv04gdoKStZ5utx2HgKsuLfE59o+WvYQsb/O+EuAZGb
+65B/2lR+Wke6QBj7pfeKOrAFNwOouCNh1Fg3l4dUV2Kqf+Zzj3T0O1cpr7v3vDNy
+1PMCIkQ+cB9IWX1uoK/EkVhMmWszKDYJWcdxp5S6Dq+H0kd1hsGsLauJgwOpl8tQ
+OcFmo6KS9shCBVvT5BMXhBBXjz6u0F73FVTdBGEv1tQlANZvAru5n/+r0qAyh6DS
+/5Epv110YdiG5YkpXsCFsQXheWhQ+iGYzCYJ0YYYTS6EITPR/7W/eC0LnoxRggmc
+A+w=
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/more-certificates/test-cn-with-drink-cert.pem b/tests/auto/network/ssl/qsslcertificate/more-certificates/test-cn-with-drink-cert.pem
new file mode 100644
index 0000000000..ed8823a520
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/more-certificates/test-cn-with-drink-cert.pem
@@ -0,0 +1,66 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 11 (0xb)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: CN=Westpoint Certificate Test CA, ST=Lancashire, C=UK/emailAddress=ca@example.com, O=Westpoint Certificate Test Root Certification Authority
+ Validity
+ Not Before: Jul 31 21:01:17 2011 GMT
+ Not After : Jul 28 21:01:17 2021 GMT
+ Subject: CN=example.com/emailAddress=test@example.com/favouriteDrink=tequila
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:b8:2a:88:dd:a3:5b:4a:44:69:03:d5:6e:18:e9:
+ 9e:55:0d:35:d0:e6:9a:c2:cc:f8:b5:c5:b6:15:00:
+ a1:24:33:af:e8:fb:93:b9:cc:b9:22:28:ef:69:57:
+ b0:a2:d0:e3:9e:e5:73:3e:90:55:5b:91:26:0b:c4:
+ 1a:a6:b6:9d:a2:68:5b:e8:5b:45:3f:21:ff:84:64:
+ a7:84:bb:61:b7:72:e7:ea:cb:49:66:40:23:be:bf:
+ f0:8d:60:f2:fb:71:b2:fc:fe:6b:e7:07:94:35:65:
+ 66:d8:06:90:82:4d:b1:ba:6c:78:f4:42:17:cb:3c:
+ 0e:10:70:21:a9:31:3b:88:41
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Authority Information Access:
+ OCSP - URI:http://ocsp.example.com:8888/
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 4b:a3:3d:37:e4:fa:61:3b:8c:94:c7:b1:49:55:a6:63:c4:b8:
+ 13:33:8c:0b:ad:c9:f6:38:d1:a6:d3:5e:7f:10:23:be:d5:4c:
+ 63:de:15:9b:eb:f1:08:0c:32:95:ff:87:bc:c7:41:c3:17:af:
+ 73:c9:ac:18:2c:3d:6d:87:9b:41:71:92:e4:57:f0:da:b7:f4:
+ f3:92:dd:db:a0:b3:82:1a:8d:88:d4:ff:b2:8e:ac:65:6f:b0:
+ 59:0a:4e:cf:12:cd:fe:ce:35:85:da:13:1c:5e:d0:30:38:8a:
+ ec:46:eb:d7:a7:87:93:1b:08:a0:28:b0:2d:fc:7d:36:51:2f:
+ df:6b:67:57:15:b3:a7:cf:dd:55:ee:81:fc:66:fc:a7:22:5f:
+ e7:86:91:0b:3f:35:56:5f:fa:41:9c:71:06:03:d0:62:d2:3b:
+ e2:08:ab:af:42:2b:1f:68:9f:17:0a:20:3b:de:a1:fa:0a:44:
+ a8:67:67:c2:96:7a:ec:fa:92:4d:8f:c8:ba:be:d7:0c:c7:c8:
+ 6d:9f:b1:6c:c8:1d:e9:b9:5c:30:f3:a2:52:43:e5:43:2a:54:
+ 24:15:b3:d5:95:af:f8:01:ab:f3:c3:3f:1d:8e:35:58:11:6c:
+ 12:82:6f:ad:c3:78:c1:cd:43:ff:93:90:25:9f:97:17:36:8e:
+ 74:28:e8:a9
+-----BEGIN CERTIFICATE-----
+MIIDOzCCAiOgAwIBAgIBCzANBgkqhkiG9w0BAQUFADCBqzEmMCQGA1UEAxMdV2Vz
+dHBvaW50IENlcnRpZmljYXRlIFRlc3QgQ0ExEzARBgNVBAgTCkxhbmNhc2hpcmUx
+CzAJBgNVBAYTAlVLMR0wGwYJKoZIhvcNAQkBFg5jYUBleGFtcGxlLmNvbTFAMD4G
+A1UEChM3V2VzdHBvaW50IENlcnRpZmljYXRlIFRlc3QgUm9vdCBDZXJ0aWZpY2F0
+aW9uIEF1dGhvcml0eTAeFw0xMTA3MzEyMTAxMTdaFw0yMTA3MjgyMTAxMTdaMFAx
+FDASBgNVBAMTC2V4YW1wbGUuY29tMR8wHQYJKoZIhvcNAQkBFhB0ZXN0QGV4YW1w
+bGUuY29tMRcwFQYKCZImiZPyLGQBBRMHdGVxdWlsYTCBnzANBgkqhkiG9w0BAQEF
+AAOBjQAwgYkCgYEAuCqI3aNbSkRpA9VuGOmeVQ010Oaawsz4tcW2FQChJDOv6PuT
+ucy5IijvaVewotDjnuVzPpBVW5EmC8Qapradomhb6FtFPyH/hGSnhLtht3Ln6stJ
+ZkAjvr/wjWDy+3Gy/P5r5weUNWVm2AaQgk2xumx49EIXyzwOEHAhqTE7iEECAwEA
+AaNIMEYwCQYDVR0TBAIwADA5BggrBgEFBQcBAQQtMCswKQYIKwYBBQUHMAGGHWh0
+dHA6Ly9vY3NwLmV4YW1wbGUuY29tOjg4ODgvMA0GCSqGSIb3DQEBBQUAA4IBAQBL
+oz035PphO4yUx7FJVaZjxLgTM4wLrcn2ONGm015/ECO+1Uxj3hWb6/EIDDKV/4e8
+x0HDF69zyawYLD1th5tBcZLkV/Dat/Tzkt3boLOCGo2I1P+yjqxlb7BZCk7PEs3+
+zjWF2hMcXtAwOIrsRuvXp4eTGwigKLAt/H02US/fa2dXFbOnz91V7oH8ZvynIl/n
+hpELPzVWX/pBnHEGA9Bi0jviCKuvQisfaJ8XCiA73qH6CkSoZ2fClnrs+pJNj8i6
+vtcMx8htn7FsyB3puVww86JSQ+VDKlQkFbPVla/4Aavzwz8djjVYEWwSgm+tw3jB
+zUP/k5Aln5cXNo50KOip
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/more-certificates/trailing-whitespace.pem b/tests/auto/network/ssl/qsslcertificate/more-certificates/trailing-whitespace.pem
new file mode 100644
index 0000000000..e48195d15e
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/more-certificates/trailing-whitespace.pem
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIIB8zCCAVwCAREwDQYJKoZIhvcNAQEFBQAwWzELMAkGA1UEBhMCQVUxEzARBgNV
+BAgTClF1ZWVuc2xhbmQxGjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMRswGQYD
+VQQDExJUZXN0IENBICgxMDI0IGJpdCkwHhcNMDcwNDE3MDc0MDI2WhcNMDcwNTE3
+MDc0MDI2WjApMRowGAYDVQQDExFuYW1lL3dpdGgvc2xhc2hlczELMAkGA1UEBhMC
+Tk8wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOud6QOsME+pWANExxgmL0iT
+1ayg++hTxHsqAYnm/FoMxfUh+NdKkgJn2/GfNppinfPOSI667VqonU+7JBZDTLV5
+CPbZIo9fFQpDJQN6naev4yaxU1VeYFfI7S8c8zYKeGSR+RenNNeLvfH80YxPpZZ1
+snv8IfDH2V8MVxiyr7lLAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAleaU4pgzV6KY
++q9QuXapUYMsC2GiNtDmkG3k+MTHUO8XlE4hqPrIM6rRf7zKQdZ950R2wL9FSnYl
+Qm1Tdv38dCka6ivMBqvRuOt9axH3m0G7nzHL7U3zaCbtEx3yVln+b3yYtiVpTuq0
+3MLrt7tQGAW6ra8ISf6YY1W65/uVXZE=
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/qsslcertificate.pro b/tests/auto/network/ssl/qsslcertificate/qsslcertificate.pro
new file mode 100644
index 0000000000..05cce8e509
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/qsslcertificate.pro
@@ -0,0 +1,29 @@
+load(qttest_p4)
+
+SOURCES += tst_qsslcertificate.cpp
+!wince*:win32:LIBS += -lws2_32
+QT = core network
+
+TARGET = tst_qsslcertificate
+
+win32 {
+ CONFIG(debug, debug|release) {
+ DESTDIR = debug
+} else {
+ DESTDIR = release
+ }
+}
+
+wince*|symbian: {
+ certFiles.files = certificates more-certificates
+ certFiles.path = .
+ DEPLOYMENT += certFiles
+}
+
+wince*: {
+ DEFINES += SRCDIR=\\\".\\\"
+} else:!symbian {
+ DEFINES += SRCDIR=\\\"$$PWD/\\\"
+}
+
+symbian:TARGET.CAPABILITY = NetworkServices ReadUserData
diff --git a/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp
new file mode 100644
index 0000000000..bcd21eefe2
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/tst_qsslcertificate.cpp
@@ -0,0 +1,995 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qsslcertificate.h>
+#include <qsslkey.h>
+#include <qsslsocket.h>
+
+#ifdef Q_OS_SYMBIAN
+// In Symbian OS test data is located in applications private dir
+// Current path (C:\private\<UID>) contains only ascii chars
+#define SRCDIR "./"
+#endif
+
+class tst_QSslCertificate : public QObject
+{
+ Q_OBJECT
+
+ struct CertInfo {
+ QFileInfo fileInfo;
+ QFileInfo fileInfo_digest_md5;
+ QFileInfo fileInfo_digest_sha1;
+ QSsl::EncodingFormat format;
+ CertInfo(const QFileInfo &fileInfo, QSsl::EncodingFormat format)
+ : fileInfo(fileInfo), format(format) {}
+ };
+
+ QList<CertInfo> certInfoList;
+ QMap<QString, QString> subjAltNameMap;
+ QMap<QString, QString> pubkeyMap;
+ QMap<QString, QString> md5Map;
+ QMap<QString, QString> sha1Map;
+
+ void createTestRows();
+#ifndef QT_NO_OPENSSL
+ void compareCertificates(const QSslCertificate & cert1, const QSslCertificate & cert2);
+#endif
+
+ QString oldCurrentDir;
+public:
+ tst_QSslCertificate();
+ virtual ~tst_QSslCertificate();
+
+public slots:
+ void initTestCase_data();
+ void init();
+ void cleanup();
+
+#ifndef QT_NO_OPENSSL
+private slots:
+ void emptyConstructor();
+ void constructor_data();
+ void constructor();
+ void constructingGarbage();
+ void copyAndAssign_data();
+ void copyAndAssign();
+ void digest_data();
+ void digest();
+ void subjectAlternativeNames_data();
+ void utf8SubjectNames();
+ void subjectAlternativeNames();
+ void publicKey_data();
+ void publicKey();
+ void toPemOrDer_data();
+ void toPemOrDer();
+ void fromDevice();
+ void fromPath_data();
+ void fromPath();
+ void certInfo();
+ void certInfoQByteArray();
+ void task256066toPem();
+ void nulInCN();
+ void nulInSan();
+ void largeSerialNumber();
+ void largeExpirationDate();
+ void blacklistedCertificates();
+ void toText();
+ void multipleCommonNames();
+ void subjectAndIssuerAttributes();
+ void verify();
+
+ // helper for verbose test failure messages
+ QString toString(const QList<QSslError>&);
+
+// ### add tests for certificate bundles (multiple certificates concatenated into a single
+// structure); both PEM and DER formatted
+#endif
+};
+
+tst_QSslCertificate::tst_QSslCertificate()
+{
+ QDir dir(SRCDIR + QLatin1String("/certificates"));
+ QFileInfoList fileInfoList = dir.entryInfoList(QDir::Files | QDir::Readable);
+ QRegExp rxCert(QLatin1String("^.+\\.(pem|der)$"));
+ QRegExp rxSan(QLatin1String("^(.+\\.(?:pem|der))\\.san$"));
+ QRegExp rxPubKey(QLatin1String("^(.+\\.(?:pem|der))\\.pubkey$"));
+ QRegExp rxDigest(QLatin1String("^(.+\\.(?:pem|der))\\.digest-(md5|sha1)$"));
+ foreach (QFileInfo fileInfo, fileInfoList) {
+ if (rxCert.indexIn(fileInfo.fileName()) >= 0)
+ certInfoList <<
+ CertInfo(fileInfo,
+ rxCert.cap(1) == QLatin1String("pem") ? QSsl::Pem : QSsl::Der);
+ if (rxSan.indexIn(fileInfo.fileName()) >= 0)
+ subjAltNameMap.insert(rxSan.cap(1), fileInfo.absoluteFilePath());
+ if (rxPubKey.indexIn(fileInfo.fileName()) >= 0)
+ pubkeyMap.insert(rxPubKey.cap(1), fileInfo.absoluteFilePath());
+ if (rxDigest.indexIn(fileInfo.fileName()) >= 0) {
+ if (rxDigest.cap(2) == QLatin1String("md5"))
+ md5Map.insert(rxDigest.cap(1), fileInfo.absoluteFilePath());
+ else
+ sha1Map.insert(rxDigest.cap(1), fileInfo.absoluteFilePath());
+ }
+ }
+}
+
+tst_QSslCertificate::~tst_QSslCertificate()
+{
+}
+
+void tst_QSslCertificate::initTestCase_data()
+{
+}
+
+void tst_QSslCertificate::init()
+{
+ QString srcdir(QLatin1String(SRCDIR));
+ if (!srcdir.isEmpty()) {
+ oldCurrentDir = QDir::current().absolutePath();
+ QDir::setCurrent(srcdir);
+ }
+}
+
+void tst_QSslCertificate::cleanup()
+{
+ if (!oldCurrentDir.isEmpty()) {
+ QDir::setCurrent(oldCurrentDir);
+ }
+
+}
+
+static QByteArray readFile(const QString &absFilePath)
+{
+ QFile file(absFilePath);
+ if (!file.open(QIODevice::ReadOnly)) {
+ QWARN("failed to open file");
+ return QByteArray();
+ }
+ return file.readAll();
+}
+
+#ifndef QT_NO_OPENSSL
+
+void tst_QSslCertificate::emptyConstructor()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QSslCertificate certificate;
+ QVERIFY(certificate.isNull());
+ //make sure none of the functions crash (task 203035)
+ QVERIFY(!certificate.isValid());
+ QCOMPARE(certificate.version() , QByteArray());
+ QCOMPARE(certificate.serialNumber(), QByteArray());
+ QCOMPARE(certificate.digest(), QCryptographicHash::hash(QByteArray(), QCryptographicHash::Md5));
+ QCOMPARE(certificate.issuerInfo(QSslCertificate::Organization), QStringList());
+ QCOMPARE(certificate.subjectInfo(QSslCertificate::Organization), QStringList());
+ QCOMPARE(certificate.subjectAlternativeNames(),(QMultiMap<QSsl::AlternativeNameEntryType, QString>()));
+#ifndef QT_NO_TEXTSTREAM
+ QCOMPARE(certificate.effectiveDate(), QDateTime());
+ QCOMPARE(certificate.expiryDate(), QDateTime());
+#endif
+}
+
+Q_DECLARE_METATYPE(QSsl::EncodingFormat);
+
+void tst_QSslCertificate::createTestRows()
+{
+ QTest::addColumn<QString>("absFilePath");
+ QTest::addColumn<QSsl::EncodingFormat>("format");
+ foreach (CertInfo certInfo, certInfoList) {
+ QTest::newRow(certInfo.fileInfo.fileName().toLatin1())
+ << certInfo.fileInfo.absoluteFilePath() << certInfo.format;
+ }
+}
+
+void tst_QSslCertificate::constructor_data()
+{
+ createTestRows();
+}
+
+void tst_QSslCertificate::constructor()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QFETCH(QString, absFilePath);
+ QFETCH(QSsl::EncodingFormat, format);
+
+ QByteArray encoded = readFile(absFilePath);
+ QSslCertificate certificate(encoded, format);
+ QVERIFY(!certificate.isNull());
+}
+
+void tst_QSslCertificate::constructingGarbage()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QByteArray garbage("garbage");
+ QSslCertificate certificate(garbage);
+ QVERIFY(certificate.isNull());
+}
+
+void tst_QSslCertificate::copyAndAssign_data()
+{
+ createTestRows();
+}
+
+void tst_QSslCertificate::compareCertificates(
+ const QSslCertificate & cert1, const QSslCertificate & cert2)
+{
+ QCOMPARE(cert1.isNull(), cert2.isNull());
+ // Note: in theory, the next line could fail even if the certificates are identical!
+ QCOMPARE(cert1.isValid(), cert2.isValid());
+ QCOMPARE(cert1.version(), cert2.version());
+ QCOMPARE(cert1.serialNumber(), cert2.serialNumber());
+ QCOMPARE(cert1.digest(), cert2.digest());
+ QCOMPARE(cert1.toPem(), cert2.toPem());
+ QCOMPARE(cert1.toDer(), cert2.toDer());
+ for (int info = QSslCertificate::Organization;
+ info <= QSslCertificate::StateOrProvinceName; info++) {
+ const QSslCertificate::SubjectInfo subjectInfo = (QSslCertificate::SubjectInfo)info;
+ QCOMPARE(cert1.issuerInfo(subjectInfo), cert2.issuerInfo(subjectInfo));
+ QCOMPARE(cert1.subjectInfo(subjectInfo), cert2.subjectInfo(subjectInfo));
+ }
+ QCOMPARE(cert1.subjectAlternativeNames(), cert2.subjectAlternativeNames());
+ QCOMPARE(cert1.effectiveDate(), cert2.effectiveDate());
+ QCOMPARE(cert1.expiryDate(), cert2.expiryDate());
+ QCOMPARE(cert1.version(), cert2.version());
+ QCOMPARE(cert1.serialNumber(), cert2.serialNumber());
+ // ### add more functions here ...
+}
+
+void tst_QSslCertificate::copyAndAssign()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QFETCH(QString, absFilePath);
+ QFETCH(QSsl::EncodingFormat, format);
+
+ QByteArray encoded = readFile(absFilePath);
+ QSslCertificate certificate(encoded, format);
+
+ QVERIFY(!certificate.isNull());
+
+ QSslCertificate copied(certificate);
+ compareCertificates(certificate, copied);
+
+ QSslCertificate assigned = certificate;
+ compareCertificates(certificate, assigned);
+}
+
+void tst_QSslCertificate::digest_data()
+{
+ QTest::addColumn<QString>("absFilePath");
+ QTest::addColumn<QSsl::EncodingFormat>("format");
+ QTest::addColumn<QString>("absFilePath_digest_md5");
+ QTest::addColumn<QString>("absFilePath_digest_sha1");
+ foreach (CertInfo certInfo, certInfoList) {
+ QString certName = certInfo.fileInfo.fileName();
+ QTest::newRow(certName.toLatin1())
+ << certInfo.fileInfo.absoluteFilePath()
+ << certInfo.format
+ << md5Map.value(certName)
+ << sha1Map.value(certName);
+ }
+}
+
+// Converts a digest of the form '{MD5|SHA1} Fingerprint=AB:B8:32...' to binary format.
+static QByteArray convertDigest(const QByteArray &input)
+{
+ QByteArray result;
+ QRegExp rx(QLatin1String("(?:=|:)([0-9A-Fa-f]{2})"));
+ int pos = 0;
+ while ((pos = rx.indexIn(input, pos)) != -1) {
+ result.append(rx.cap(1).toLatin1());
+ pos += rx.matchedLength();
+ }
+ return QByteArray::fromHex(result);
+}
+
+void tst_QSslCertificate::digest()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QFETCH(QString, absFilePath);
+ QFETCH(QSsl::EncodingFormat, format);
+ QFETCH(QString, absFilePath_digest_md5);
+ QFETCH(QString, absFilePath_digest_sha1);
+
+ QByteArray encoded = readFile(absFilePath);
+ QSslCertificate certificate(encoded, format);
+ QVERIFY(!certificate.isNull());
+
+ if (!absFilePath_digest_md5.isEmpty())
+ QCOMPARE(convertDigest(readFile(absFilePath_digest_md5)),
+ certificate.digest(QCryptographicHash::Md5));
+
+ if (!absFilePath_digest_sha1.isEmpty())
+ QCOMPARE(convertDigest(readFile(absFilePath_digest_sha1)),
+ certificate.digest(QCryptographicHash::Sha1));
+}
+
+void tst_QSslCertificate::subjectAlternativeNames_data()
+{
+ QTest::addColumn<QString>("certFilePath");
+ QTest::addColumn<QSsl::EncodingFormat>("format");
+ QTest::addColumn<QString>("subjAltNameFilePath");
+
+ foreach (CertInfo certInfo, certInfoList) {
+ QString certName = certInfo.fileInfo.fileName();
+ if (subjAltNameMap.contains(certName))
+ QTest::newRow(certName.toLatin1())
+ << certInfo.fileInfo.absoluteFilePath()
+ << certInfo.format
+ << subjAltNameMap.value(certName);
+ }
+}
+
+void tst_QSslCertificate::subjectAlternativeNames()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QFETCH(QString, certFilePath);
+ QFETCH(QSsl::EncodingFormat, format);
+ QFETCH(QString, subjAltNameFilePath);
+
+ QByteArray encodedCert = readFile(certFilePath);
+ QSslCertificate certificate(encodedCert, format);
+ QVERIFY(!certificate.isNull());
+
+ QByteArray fileContents = readFile(subjAltNameFilePath);
+
+ const QMultiMap<QSsl::AlternativeNameEntryType, QString> altSubjectNames =
+ certificate.subjectAlternativeNames();
+
+ // verify that each entry in subjAltNames is present in fileContents
+ QMapIterator<QSsl::AlternativeNameEntryType, QString> it(altSubjectNames);
+ while (it.hasNext()) {
+ it.next();
+ QString type;
+ if (it.key() == QSsl::EmailEntry)
+ type = QLatin1String("email");
+ else if (it.key() == QSsl::DnsEntry)
+ type = QLatin1String("DNS");
+ else
+ QFAIL("unsupported alternative name type");
+ QString entry = QString("%1:%2").arg(type).arg(it.value());
+ QVERIFY(fileContents.contains(entry.toAscii()));
+ }
+
+ // verify that each entry in fileContents is present in subjAltNames
+ QRegExp rx(QLatin1String("(email|DNS):([^,\\r\\n]+)"));
+ for (int pos = 0; (pos = rx.indexIn(fileContents, pos)) != -1; pos += rx.matchedLength()) {
+ QSsl::AlternativeNameEntryType key;
+ if (rx.cap(1) == QLatin1String("email"))
+ key = QSsl::EmailEntry;
+ else if (rx.cap(1) == QLatin1String("DNS"))
+ key = QSsl::DnsEntry;
+ else
+ QFAIL("unsupported alternative name type");
+ QVERIFY(altSubjectNames.contains(key, rx.cap(2)));
+ }
+}
+
+void tst_QSslCertificate::utf8SubjectNames()
+{
+ QSslCertificate cert = QSslCertificate::fromPath("certificates/cert-ss-san-utf8.pem", QSsl::Pem,
+ QRegExp::FixedString).first();
+ QVERIFY(!cert.isNull());
+
+ // O is "Heavy Metal Records" with heavy use of "decorations" like accents, umlauts etc.,
+ // OU uses arabian / asian script letters near codepoint 64K.
+ // strings split where the compiler would otherwise find three-digit hex numbers
+ static const char *o = "H\xc4\x95\xc4\x82\xc6\xb2\xc3\xbf \xca\x8d\xe1\xba\xbf\xca\x88\xe1\xba"
+ "\xb7\xe1\xb8\xbb R\xc3\xa9" "c" "\xc3\xb6rd\xc5\x9d";
+ static const char *ou = "\xe3\x88\xa7" "A" "\xe3\x89\x81\xef\xbd\xab" "BC";
+
+ // the following two tests should help find "\x"-literal encoding bugs in the test itself
+ QCOMPARE(cert.subjectInfo("O")[0].length(), QString::fromUtf8(o).length());
+ QCOMPARE (cert.subjectInfo("O")[0].toUtf8().toHex(), QByteArray(o).toHex());
+
+ QCOMPARE(cert.subjectInfo("O")[0], QString::fromUtf8(o));
+ QCOMPARE(cert.subjectInfo("OU")[0], QString::fromUtf8(ou));
+}
+
+void tst_QSslCertificate::publicKey_data()
+{
+ QTest::addColumn<QString>("certFilePath");
+ QTest::addColumn<QSsl::EncodingFormat>("format");
+ QTest::addColumn<QString>("pubkeyFilePath");
+
+ foreach (CertInfo certInfo, certInfoList) {
+ QString certName = certInfo.fileInfo.fileName();
+ if (pubkeyMap.contains(certName))
+ QTest::newRow(certName.toLatin1())
+ << certInfo.fileInfo.absoluteFilePath()
+ << certInfo.format
+ << pubkeyMap.value(certName);
+ }
+}
+
+void tst_QSslCertificate::publicKey()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QFETCH(QString, certFilePath);
+ QFETCH(QSsl::EncodingFormat, format);
+ QFETCH(QString, pubkeyFilePath);
+
+ QByteArray encodedCert = readFile(certFilePath);
+ QSslCertificate certificate(encodedCert, format);
+ QVERIFY(!certificate.isNull());
+
+ QByteArray encodedPubkey = readFile(pubkeyFilePath);
+ QSslKey pubkey(encodedPubkey, QSsl::Rsa, format, QSsl::PublicKey); // ### support DSA as well!
+ QVERIFY(!pubkey.isNull());
+
+ QCOMPARE(certificate.publicKey(), pubkey);
+}
+
+void tst_QSslCertificate::toPemOrDer_data()
+{
+ createTestRows();
+}
+
+static const char BeginCertString[] = "-----BEGIN CERTIFICATE-----";
+static const char EndCertString[] = "-----END CERTIFICATE-----";
+
+// Returns, in Pem-format, the first certificate found in a Pem-formatted block
+// (Note that such a block may contain e.g. a private key at the end).
+static QByteArray firstPemCertificateFromPem(const QByteArray &pem)
+{
+ int startPos = pem.indexOf(BeginCertString);
+ int endPos = pem.indexOf(EndCertString);
+ if (startPos == -1 || endPos == -1)
+ return QByteArray();
+ return pem.mid(startPos, endPos + sizeof(EndCertString) - startPos);
+}
+
+void tst_QSslCertificate::toPemOrDer()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QFETCH(QString, absFilePath);
+ QFETCH(QSsl::EncodingFormat, format);
+
+ QByteArray encoded = readFile(absFilePath);
+ QSslCertificate certificate(encoded, format);
+ QVERIFY(!certificate.isNull());
+ if (format == QSsl::Pem) {
+ encoded.replace('\r',"");
+ QByteArray firstPem = firstPemCertificateFromPem(encoded);
+ QCOMPARE(certificate.toPem(), firstPem);
+ } else {
+ // ### for now, we assume that DER-encoded certificates don't contain bundled stuff
+ QCOMPARE(certificate.toDer(), encoded);
+ }
+}
+
+void tst_QSslCertificate::fromDevice()
+{
+ QTest::ignoreMessage(QtWarningMsg, "QSslCertificate::fromDevice: cannot read from a null device");
+ QList<QSslCertificate> certs = QSslCertificate::fromDevice(0); // don't crash
+ QVERIFY(certs.isEmpty());
+}
+
+void tst_QSslCertificate::fromPath_data()
+{
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<int>("syntax");
+ QTest::addColumn<bool>("pemencoding");
+ QTest::addColumn<int>("numCerts");
+
+ QTest::newRow("empty fixed pem") << QString() << int(QRegExp::FixedString) << true << 0;
+ QTest::newRow("empty fixed der") << QString() << int(QRegExp::FixedString) << false << 0;
+ QTest::newRow("empty regexp pem") << QString() << int(QRegExp::RegExp) << true << 0;
+ QTest::newRow("empty regexp der") << QString() << int(QRegExp::RegExp) << false << 0;
+ QTest::newRow("empty wildcard pem") << QString() << int(QRegExp::Wildcard) << true << 0;
+ QTest::newRow("empty wildcard der") << QString() << int(QRegExp::Wildcard) << false << 0;
+ QTest::newRow("\"certificates\" fixed pem") << QString("certificates") << int(QRegExp::FixedString) << true << 0;
+ QTest::newRow("\"certificates\" fixed der") << QString("certificates") << int(QRegExp::FixedString) << false << 0;
+ QTest::newRow("\"certificates\" regexp pem") << QString("certificates") << int(QRegExp::RegExp) << true << 0;
+ QTest::newRow("\"certificates\" regexp der") << QString("certificates") << int(QRegExp::RegExp) << false << 0;
+ QTest::newRow("\"certificates\" wildcard pem") << QString("certificates") << int(QRegExp::Wildcard) << true << 0;
+ QTest::newRow("\"certificates\" wildcard der") << QString("certificates") << int(QRegExp::Wildcard) << false << 0;
+ QTest::newRow("\"certificates/cert.pem\" fixed pem") << QString("certificates/cert.pem") << int(QRegExp::FixedString) << true << 1;
+ QTest::newRow("\"certificates/cert.pem\" fixed der") << QString("certificates/cert.pem") << int(QRegExp::FixedString) << false << 0;
+ QTest::newRow("\"certificates/cert.pem\" regexp pem") << QString("certificates/cert.pem") << int(QRegExp::RegExp) << true << 1;
+ QTest::newRow("\"certificates/cert.pem\" regexp der") << QString("certificates/cert.pem") << int(QRegExp::RegExp) << false << 0;
+ QTest::newRow("\"certificates/cert.pem\" wildcard pem") << QString("certificates/cert.pem") << int(QRegExp::Wildcard) << true << 1;
+ QTest::newRow("\"certificates/cert.pem\" wildcard der") << QString("certificates/cert.pem") << int(QRegExp::Wildcard) << false << 0;
+ QTest::newRow("\"certificates/*\" fixed pem") << QString("certificates/*") << int(QRegExp::FixedString) << true << 0;
+ QTest::newRow("\"certificates/*\" fixed der") << QString("certificates/*") << int(QRegExp::FixedString) << false << 0;
+ QTest::newRow("\"certificates/*\" regexp pem") << QString("certificates/*") << int(QRegExp::RegExp) << true << 0;
+ QTest::newRow("\"certificates/*\" regexp der") << QString("certificates/*") << int(QRegExp::RegExp) << false << 0;
+ QTest::newRow("\"certificates/*\" wildcard pem") << QString("certificates/*") << int(QRegExp::Wildcard) << true << 5;
+ QTest::newRow("\"certificates/*\" wildcard der") << QString("certificates/*") << int(QRegExp::Wildcard) << false << 0;
+ QTest::newRow("\"c*/c*.pem\" fixed pem") << QString("c*/c*.pem") << int(QRegExp::FixedString) << true << 0;
+ QTest::newRow("\"c*/c*.pem\" fixed der") << QString("c*/c*.pem") << int(QRegExp::FixedString) << false << 0;
+ QTest::newRow("\"c*/c*.pem\" regexp pem") << QString("c*/c*.pem") << int(QRegExp::RegExp) << true << 0;
+ QTest::newRow("\"c*/c*.pem\" regexp der") << QString("c*/c*.pem") << int(QRegExp::RegExp) << false << 0;
+ QTest::newRow("\"c*/c*.pem\" wildcard pem") << QString("c*/c*.pem") << int(QRegExp::Wildcard) << true << 5;
+ QTest::newRow("\"c*/c*.pem\" wildcard der") << QString("c*/c*.pem") << int(QRegExp::Wildcard) << false << 0;
+ QTest::newRow("\"d*/c*.pem\" fixed pem") << QString("d*/c*.pem") << int(QRegExp::FixedString) << true << 0;
+ QTest::newRow("\"d*/c*.pem\" fixed der") << QString("d*/c*.pem") << int(QRegExp::FixedString) << false << 0;
+ QTest::newRow("\"d*/c*.pem\" regexp pem") << QString("d*/c*.pem") << int(QRegExp::RegExp) << true << 0;
+ QTest::newRow("\"d*/c*.pem\" regexp der") << QString("d*/c*.pem") << int(QRegExp::RegExp) << false << 0;
+ QTest::newRow("\"d*/c*.pem\" wildcard pem") << QString("d*/c*.pem") << int(QRegExp::Wildcard) << true << 0;
+ QTest::newRow("\"d*/c*.pem\" wildcard der") << QString("d*/c*.pem") << int(QRegExp::Wildcard) << false << 0;
+ QTest::newRow("\"c.*/c.*.pem\" fixed pem") << QString("c.*/c.*.pem") << int(QRegExp::FixedString) << true << 0;
+ QTest::newRow("\"c.*/c.*.pem\" fixed der") << QString("c.*/c.*.pem") << int(QRegExp::FixedString) << false << 0;
+ QTest::newRow("\"c.*/c.*.pem\" regexp pem") << QString("c.*/c.*.pem") << int(QRegExp::RegExp) << true << 5;
+ QTest::newRow("\"c.*/c.*.pem\" regexp der") << QString("c.*/c.*.pem") << int(QRegExp::RegExp) << false << 0;
+ QTest::newRow("\"c.*/c.*.pem\" wildcard pem") << QString("c.*/c.*.pem") << int(QRegExp::Wildcard) << true << 0;
+ QTest::newRow("\"c.*/c.*.pem\" wildcard der") << QString("c.*/c.*.pem") << int(QRegExp::Wildcard) << false << 0;
+ QTest::newRow("\"d.*/c.*.pem\" fixed pem") << QString("d.*/c.*.pem") << int(QRegExp::FixedString) << true << 0;
+ QTest::newRow("\"d.*/c.*.pem\" fixed der") << QString("d.*/c.*.pem") << int(QRegExp::FixedString) << false << 0;
+ QTest::newRow("\"d.*/c.*.pem\" regexp pem") << QString("d.*/c.*.pem") << int(QRegExp::RegExp) << true << 0;
+ QTest::newRow("\"d.*/c.*.pem\" regexp der") << QString("d.*/c.*.pem") << int(QRegExp::RegExp) << false << 0;
+ QTest::newRow("\"d.*/c.*.pem\" wildcard pem") << QString("d.*/c.*.pem") << int(QRegExp::Wildcard) << true << 0;
+ QTest::newRow("\"d.*/c.*.pem\" wildcard der") << QString("d.*/c.*.pem") << int(QRegExp::Wildcard) << false << 0;
+#ifdef Q_OS_LINUX
+ QTest::newRow("absolute path wildcard pem") << QString(QDir::currentPath() + "/certificates/*.pem") << int(QRegExp::Wildcard) << true << 5;
+#endif
+
+ QTest::newRow("trailing-whitespace") << QString("more-certificates/trailing-whitespace.pem") << int(QRegExp::FixedString) << true << 1;
+ QTest::newRow("no-ending-newline") << QString("more-certificates/no-ending-newline.pem") << int(QRegExp::FixedString) << true << 1;
+ QTest::newRow("malformed-just-begin") << QString("more-certificates/malformed-just-begin.pem") << int(QRegExp::FixedString) << true << 0;
+ QTest::newRow("malformed-just-begin-no-newline") << QString("more-certificates/malformed-just-begin-no-newline.pem") << int(QRegExp::FixedString) << true << 0;
+}
+
+void tst_QSslCertificate::fromPath()
+{
+ QFETCH(QString, path);
+ QFETCH(int, syntax);
+ QFETCH(bool, pemencoding);
+ QFETCH(int, numCerts);
+
+ QCOMPARE(QSslCertificate::fromPath(path,
+ pemencoding ? QSsl::Pem : QSsl::Der,
+ QRegExp::PatternSyntax(syntax)).size(),
+ numCerts);
+}
+
+void tst_QSslCertificate::certInfo()
+{
+// MD5 Fingerprint=B6:CF:57:34:DA:A9:73:21:82:F7:CF:4D:3D:85:31:88
+// SHA1 Fingerprint=B6:D1:51:82:E0:29:CA:59:96:38:BD:B6:F9:40:05:91:6D:49:09:60
+// Certificate:
+// Data:
+// Version: 1 (0x0)
+// Serial Number: 17 (0x11)
+// Signature Algorithm: sha1WithRSAEncryption
+// Issuer: C=AU, ST=Queensland, O=CryptSoft Pty Ltd, CN=Test CA (1024 bit)
+// Validity
+// Not Before: Apr 17 07:40:26 2007 GMT
+// Not After : May 17 07:40:26 2007 GMT
+// Subject: CN=name/with/slashes, C=NO
+// Subject Public Key Info:
+// Public Key Algorithm: rsaEncryption
+// RSA Public Key: (1024 bit)
+// Modulus (1024 bit):
+// 00:eb:9d:e9:03:ac:30:4f:a9:58:03:44:c7:18:26:
+// 2f:48:93:d5:ac:a0:fb:e8:53:c4:7b:2a:01:89:e6:
+// fc:5a:0c:c5:f5:21:f8:d7:4a:92:02:67:db:f1:9f:
+// 36:9a:62:9d:f3:ce:48:8e:ba:ed:5a:a8:9d:4f:bb:
+// 24:16:43:4c:b5:79:08:f6:d9:22:8f:5f:15:0a:43:
+// 25:03:7a:9d:a7:af:e3:26:b1:53:55:5e:60:57:c8:
+// ed:2f:1c:f3:36:0a:78:64:91:f9:17:a7:34:d7:8b:
+// bd:f1:fc:d1:8c:4f:a5:96:75:b2:7b:fc:21:f0:c7:
+// d9:5f:0c:57:18:b2:af:b9:4b
+// Exponent: 65537 (0x10001)
+// Signature Algorithm: sha1WithRSAEncryption
+// 95:e6:94:e2:98:33:57:a2:98:fa:af:50:b9:76:a9:51:83:2c:
+// 0b:61:a2:36:d0:e6:90:6d:e4:f8:c4:c7:50:ef:17:94:4e:21:
+// a8:fa:c8:33:aa:d1:7f:bc:ca:41:d6:7d:e7:44:76:c0:bf:45:
+// 4a:76:25:42:6d:53:76:fd:fc:74:29:1a:ea:2b:cc:06:ab:d1:
+// b8:eb:7d:6b:11:f7:9b:41:bb:9f:31:cb:ed:4d:f3:68:26:ed:
+// 13:1d:f2:56:59:fe:6f:7c:98:b6:25:69:4e:ea:b4:dc:c2:eb:
+// b7:bb:50:18:05:ba:ad:af:08:49:fe:98:63:55:ba:e7:fb:95:
+// 5d:91
+ static const char pem[] =
+ "-----BEGIN CERTIFICATE-----\n"
+ "MIIB8zCCAVwCAREwDQYJKoZIhvcNAQEFBQAwWzELMAkGA1UEBhMCQVUxEzARBgNV\n"
+ "BAgTClF1ZWVuc2xhbmQxGjAYBgNVBAoTEUNyeXB0U29mdCBQdHkgTHRkMRswGQYD\n"
+ "VQQDExJUZXN0IENBICgxMDI0IGJpdCkwHhcNMDcwNDE3MDc0MDI2WhcNMDcwNTE3\n"
+ "MDc0MDI2WjApMRowGAYDVQQDExFuYW1lL3dpdGgvc2xhc2hlczELMAkGA1UEBhMC\n"
+ "Tk8wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOud6QOsME+pWANExxgmL0iT\n"
+ "1ayg++hTxHsqAYnm/FoMxfUh+NdKkgJn2/GfNppinfPOSI667VqonU+7JBZDTLV5\n"
+ "CPbZIo9fFQpDJQN6naev4yaxU1VeYFfI7S8c8zYKeGSR+RenNNeLvfH80YxPpZZ1\n"
+ "snv8IfDH2V8MVxiyr7lLAgMBAAEwDQYJKoZIhvcNAQEFBQADgYEAleaU4pgzV6KY\n"
+ "+q9QuXapUYMsC2GiNtDmkG3k+MTHUO8XlE4hqPrIM6rRf7zKQdZ950R2wL9FSnYl\n"
+ "Qm1Tdv38dCka6ivMBqvRuOt9axH3m0G7nzHL7U3zaCbtEx3yVln+b3yYtiVpTuq0\n"
+ "3MLrt7tQGAW6ra8ISf6YY1W65/uVXZE=\n"
+ "-----END CERTIFICATE-----\n";
+ static const char der[] = // hex encoded
+ "30:82:01:f3:30:82:01:5c:02:01:11:30:0d:06:09:2a"
+ "86:48:86:f7:0d:01:01:05:05:00:30:5b:31:0b:30:09"
+ "06:03:55:04:06:13:02:41:55:31:13:30:11:06:03:55"
+ "04:08:13:0a:51:75:65:65:6e:73:6c:61:6e:64:31:1a"
+ "30:18:06:03:55:04:0a:13:11:43:72:79:70:74:53:6f"
+ "66:74:20:50:74:79:20:4c:74:64:31:1b:30:19:06:03"
+ "55:04:03:13:12:54:65:73:74:20:43:41:20:28:31:30"
+ "32:34:20:62:69:74:29:30:1e:17:0d:30:37:30:34:31"
+ "37:30:37:34:30:32:36:5a:17:0d:30:37:30:35:31:37"
+ "30:37:34:30:32:36:5a:30:29:31:1a:30:18:06:03:55"
+ "04:03:13:11:6e:61:6d:65:2f:77:69:74:68:2f:73:6c"
+ "61:73:68:65:73:31:0b:30:09:06:03:55:04:06:13:02"
+ "4e:4f:30:81:9f:30:0d:06:09:2a:86:48:86:f7:0d:01"
+ "01:01:05:00:03:81:8d:00:30:81:89:02:81:81:00:eb"
+ "9d:e9:03:ac:30:4f:a9:58:03:44:c7:18:26:2f:48:93"
+ "d5:ac:a0:fb:e8:53:c4:7b:2a:01:89:e6:fc:5a:0c:c5"
+ "f5:21:f8:d7:4a:92:02:67:db:f1:9f:36:9a:62:9d:f3"
+ "ce:48:8e:ba:ed:5a:a8:9d:4f:bb:24:16:43:4c:b5:79"
+ "08:f6:d9:22:8f:5f:15:0a:43:25:03:7a:9d:a7:af:e3"
+ "26:b1:53:55:5e:60:57:c8:ed:2f:1c:f3:36:0a:78:64"
+ "91:f9:17:a7:34:d7:8b:bd:f1:fc:d1:8c:4f:a5:96:75"
+ "b2:7b:fc:21:f0:c7:d9:5f:0c:57:18:b2:af:b9:4b:02"
+ "03:01:00:01:30:0d:06:09:2a:86:48:86:f7:0d:01:01"
+ "05:05:00:03:81:81:00:95:e6:94:e2:98:33:57:a2:98"
+ "fa:af:50:b9:76:a9:51:83:2c:0b:61:a2:36:d0:e6:90"
+ "6d:e4:f8:c4:c7:50:ef:17:94:4e:21:a8:fa:c8:33:aa"
+ "d1:7f:bc:ca:41:d6:7d:e7:44:76:c0:bf:45:4a:76:25"
+ "42:6d:53:76:fd:fc:74:29:1a:ea:2b:cc:06:ab:d1:b8"
+ "eb:7d:6b:11:f7:9b:41:bb:9f:31:cb:ed:4d:f3:68:26"
+ "ed:13:1d:f2:56:59:fe:6f:7c:98:b6:25:69:4e:ea:b4"
+ "dc:c2:eb:b7:bb:50:18:05:ba:ad:af:08:49:fe:98:63"
+ "55:ba:e7:fb:95:5d:91";
+
+ QSslCertificate cert = QSslCertificate::fromPath("certificates/cert.pem", QSsl::Pem,
+ QRegExp::FixedString).first();
+ QVERIFY(!cert.isNull());
+
+ QCOMPARE(cert.issuerInfo(QSslCertificate::Organization)[0], QString("CryptSoft Pty Ltd"));
+ QCOMPARE(cert.issuerInfo(QSslCertificate::CommonName)[0], QString("Test CA (1024 bit)"));
+ QCOMPARE(cert.issuerInfo(QSslCertificate::LocalityName), QStringList());
+ QCOMPARE(cert.issuerInfo(QSslCertificate::OrganizationalUnitName), QStringList());
+ QCOMPARE(cert.issuerInfo(QSslCertificate::CountryName)[0], QString("AU"));
+ QCOMPARE(cert.issuerInfo(QSslCertificate::StateOrProvinceName)[0], QString("Queensland"));
+
+ QCOMPARE(cert.issuerInfo("O")[0], QString("CryptSoft Pty Ltd"));
+ QCOMPARE(cert.issuerInfo("CN")[0], QString("Test CA (1024 bit)"));
+ QCOMPARE(cert.issuerInfo("L"), QStringList());
+ QCOMPARE(cert.issuerInfo("OU"), QStringList());
+ QCOMPARE(cert.issuerInfo("C")[0], QString("AU"));
+ QCOMPARE(cert.issuerInfo("ST")[0], QString("Queensland"));
+
+ QCOMPARE(cert.subjectInfo(QSslCertificate::Organization), QStringList());
+ QCOMPARE(cert.subjectInfo(QSslCertificate::CommonName)[0], QString("name/with/slashes"));
+ QCOMPARE(cert.subjectInfo(QSslCertificate::LocalityName), QStringList());
+ QCOMPARE(cert.subjectInfo(QSslCertificate::OrganizationalUnitName), QStringList());
+ QCOMPARE(cert.subjectInfo(QSslCertificate::CountryName)[0], QString("NO"));
+ QCOMPARE(cert.subjectInfo(QSslCertificate::StateOrProvinceName), QStringList());
+
+ QCOMPARE(cert.subjectInfo("O"), QStringList());
+ QCOMPARE(cert.subjectInfo("CN")[0], QString("name/with/slashes"));
+ QCOMPARE(cert.subjectInfo("L"), QStringList());
+ QCOMPARE(cert.subjectInfo("OU"), QStringList());
+ QCOMPARE(cert.subjectInfo("C")[0], QString("NO"));
+ QCOMPARE(cert.subjectInfo("ST"), QStringList());
+
+ QCOMPARE(cert.version(), QByteArray::number(1));
+ QCOMPARE(cert.serialNumber(), QByteArray::number(17));
+
+ QCOMPARE(cert.toPem().constData(), (const char*)pem);
+ QCOMPARE(cert.toDer(), QByteArray::fromHex(der));
+
+ QCOMPARE(cert.digest(QCryptographicHash::Md5),
+ QByteArray::fromHex("B6:CF:57:34:DA:A9:73:21:82:F7:CF:4D:3D:85:31:88"));
+ QCOMPARE(cert.digest(QCryptographicHash::Sha1),
+ QByteArray::fromHex("B6:D1:51:82:E0:29:CA:59:96:38:BD:B6:F9:40:05:91:6D:49:09:60"));
+
+ QCOMPARE(cert.effectiveDate().toUTC(), QDateTime(QDate(2007, 4, 17), QTime(7,40,26), Qt::UTC));
+ QCOMPARE(cert.expiryDate().toUTC(), QDateTime(QDate(2007, 5, 17), QTime(7,40,26), Qt::UTC));
+ QVERIFY(!cert.isValid()); // cert has expired
+
+ QSslCertificate copy = cert;
+ QVERIFY(cert == copy);
+ QVERIFY(!(cert != copy));
+
+ QCOMPARE(cert, QSslCertificate(pem, QSsl::Pem));
+ QCOMPARE(cert, QSslCertificate(QByteArray::fromHex(der), QSsl::Der));
+}
+
+void tst_QSslCertificate::certInfoQByteArray()
+{
+ QSslCertificate cert = QSslCertificate::fromPath("certificates/cert.pem", QSsl::Pem,
+ QRegExp::FixedString).first();
+ QVERIFY(!cert.isNull());
+
+ // in this test, check the bytearray variants before the enum variants to see if
+ // we fixed a bug we had with lazy initialization of the values.
+ QCOMPARE(cert.issuerInfo("CN")[0], QString("Test CA (1024 bit)"));
+ QCOMPARE(cert.subjectInfo("CN")[0], QString("name/with/slashes"));
+}
+
+void tst_QSslCertificate::task256066toPem()
+{
+ // a certificate whose PEM encoding's length is a multiple of 64
+ const char *mycert = "-----BEGIN CERTIFICATE-----\n" \
+ "MIIEGjCCAwKgAwIBAgIESikYSjANBgkqhkiG9w0BAQUFADBbMQswCQYDVQQGEwJF\n" \
+ "RTEiMCAGA1UEChMZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEPMA0GA1UECxMG\n" \
+ "RVNURUlEMRcwFQYDVQQDEw5FU1RFSUQtU0sgMjAwNzAeFw0wOTA2MDUxMzA2MTha\n" \
+ "Fw0xNDA2MDkyMTAwMDBaMIGRMQswCQYDVQQGEwJFRTEPMA0GA1UEChMGRVNURUlE\n" \
+ "MRcwFQYDVQQLEw5hdXRoZW50aWNhdGlvbjEhMB8GA1UEAxMYSEVJQkVSRyxTVkVO\n" \
+ "LDM3NzA5MjcwMjg1MRAwDgYDVQQEEwdIRUlCRVJHMQ0wCwYDVQQqEwRTVkVOMRQw\n" \
+ "EgYDVQQFEwszNzcwOTI3MDI4NTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA\n" \
+ "k2Euwhm34vu1jOFp02J5fQRx9LW2C7x78CbJ7yInoAKn7QR8UdxTU7mJk90Opejo\n" \
+ "71RUi2/aYl4jCr9gr99v2YoLufMRwAuqdmwmwqH1WAHRUtIcD0oPdKyelmmn9ig0\n" \
+ "RV+yJLNT3dnyrwPw+uuzDe3DeKepGKE4lxexliCaAx0CAyCMW6OCATEwggEtMA4G\n" \
+ "A1UdDwEB/wQEAwIEsDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwQwPAYD\n" \
+ "VR0fBDUwMzAxoC+gLYYraHR0cDovL3d3dy5zay5lZS9jcmxzL2VzdGVpZC9lc3Rl\n" \
+ "aWQyMDA3LmNybDAgBgNVHREEGTAXgRVzdmVuLmhlaWJlcmdAZWVzdGkuZWUwUQYD\n" \
+ "VR0gBEowSDBGBgsrBgEEAc4fAQEBATA3MBIGCCsGAQUFBwICMAYaBG5vbmUwIQYI\n" \
+ "KwYBBQUHAgEWFWh0dHA6Ly93d3cuc2suZWUvY3BzLzAfBgNVHSMEGDAWgBRIBt6+\n" \
+ "jIdXlYB4Y/qcIysroDoYdTAdBgNVHQ4EFgQUKCjpDf+LcvL6AH0QOiW6rMTtB/0w\n" \
+ "CQYDVR0TBAIwADANBgkqhkiG9w0BAQUFAAOCAQEABRyRuUm9zt8V27WuNeXtCDmU\n" \
+ "MGzA6g4QXNAd2nxFzT3k+kNzzQTOcgRdmjiEPuK49On+GWnBr/5MSBNhbCJVPWr/\n" \
+ "yym1UYTBisaqhRt/N/kwZqd0bHeLJk+ZxSePXRyqkp9H8KPWqz7H+O/FxRS4ffxo\n" \
+ "Q9Clem+e0bcjNlL5xXiRGycBeZq8cKj+0+A/UuattznQlvHdlCEsSeu1fPOORqFV\n" \
+ "fZur4HC31lQD7xVvETLiL83CtOQC78+29XPD6Zlrrc5OF2yibSVParY19b8Zh6yu\n" \
+ "p1dNvN8pBgXGrsyxRonwHooV2ghGNmGILkpdvlQfnxeCUg4erfHjDdSY9vmT7w==\n" \
+ "-----END CERTIFICATE-----\n";
+
+ QByteArray pem1(mycert);
+ QSslCertificate cert1(pem1);
+ QVERIFY(!cert1.isNull());
+ QByteArray pem2(cert1.toPem());
+ QSslCertificate cert2(pem2);
+ QVERIFY(!cert2.isNull());
+ QCOMPARE(pem1, pem2);
+}
+
+void tst_QSslCertificate::nulInCN()
+{
+ QList<QSslCertificate> certList =
+ QSslCertificate::fromPath(SRCDIR "more-certificates/badguy-nul-cn.crt");
+ QCOMPARE(certList.size(), 1);
+
+ const QSslCertificate &cert = certList.at(0);
+ QVERIFY(!cert.isNull());
+
+ QString cn = cert.subjectInfo(QSslCertificate::CommonName)[0];
+ QVERIFY(cn != "www.bank.com");
+
+ static const char realCN[] = "www.bank.com\0.badguy.com";
+ QCOMPARE(cn, QString::fromLatin1(realCN, sizeof realCN - 1));
+}
+
+void tst_QSslCertificate::nulInSan()
+{
+ QList<QSslCertificate> certList =
+ QSslCertificate::fromPath(SRCDIR "more-certificates/badguy-nul-san.crt");
+ QCOMPARE(certList.size(), 1);
+
+ const QSslCertificate &cert = certList.at(0);
+ QVERIFY(!cert.isNull());
+
+ QMultiMap<QSsl::AlternativeNameEntryType, QString> san = cert.subjectAlternativeNames();
+ QVERIFY(!san.isEmpty());
+
+ QString dnssan = san.value(QSsl::DnsEntry);
+ QVERIFY(!dnssan.isEmpty());
+ QVERIFY(dnssan != "www.bank.com");
+
+ static const char realSAN[] = "www.bank.com\0www.badguy.com";
+ QCOMPARE(dnssan, QString::fromLatin1(realSAN, sizeof realSAN - 1));
+}
+
+void tst_QSslCertificate::largeSerialNumber()
+{
+ QList<QSslCertificate> certList =
+ QSslCertificate::fromPath(SRCDIR "more-certificates/cert-large-serial-number.pem");
+
+ QCOMPARE(certList.size(), 1);
+
+ const QSslCertificate &cert = certList.at(0);
+ QVERIFY(!cert.isNull());
+ QCOMPARE(cert.serialNumber(), QByteArray("01:02:03:04:05:06:07:08:09:10:aa:bb:cc:dd:ee:ff:17:18:19:20"));
+}
+
+void tst_QSslCertificate::largeExpirationDate() // QTBUG-12489
+{
+ QList<QSslCertificate> certList =
+ QSslCertificate::fromPath(SRCDIR "more-certificates/cert-large-expiration-date.pem");
+
+ QCOMPARE(certList.size(), 1);
+
+ const QSslCertificate &cert = certList.at(0);
+ QVERIFY(!cert.isNull());
+ QCOMPARE(cert.effectiveDate().toUTC(), QDateTime(QDate(2010, 8, 4), QTime(9, 53, 41), Qt::UTC));
+ // if the date is larger than 2049, then the generalized time format is used
+ QCOMPARE(cert.expiryDate().toUTC(), QDateTime(QDate(2051, 8, 29), QTime(9, 53, 41), Qt::UTC));
+}
+
+void tst_QSslCertificate::blacklistedCertificates()
+{
+ QList<QSslCertificate> blacklistedCerts = QSslCertificate::fromPath("more-certificates/blacklisted*.pem", QSsl::Pem, QRegExp::Wildcard);
+ QVERIFY2(blacklistedCerts.count() > 0, "Please run this test from the source directory");
+ for (int a = 0; a < blacklistedCerts.count(); a++) {
+ QVERIFY(! blacklistedCerts.at(a).isValid());
+ }
+}
+
+void tst_QSslCertificate::toText()
+{
+ QList<QSslCertificate> certList =
+ QSslCertificate::fromPath(SRCDIR "more-certificates/cert-large-expiration-date.pem");
+
+ QCOMPARE(certList.size(), 1);
+ const QSslCertificate &cert = certList.at(0);
+
+ // Openssl's cert dump method changed slightly between 0.9.8 and 1.0.0 versions, so we want it to match any output
+
+ QFile fOld(SRCDIR "more-certificates/cert-large-expiration-date.txt.0.9.8");
+ QVERIFY(fOld.open(QIODevice::ReadOnly));
+ QByteArray txtOld = fOld.readAll();
+
+ QFile fNew(SRCDIR "more-certificates/cert-large-expiration-date.txt.1.0.0");
+ QVERIFY(fNew.open(QIODevice::ReadOnly));
+ QByteArray txtNew = fNew.readAll();
+ QVERIFY(txtOld == cert.toText() || txtNew == cert.toText());
+}
+
+void tst_QSslCertificate::multipleCommonNames()
+{
+ QList<QSslCertificate> certList =
+ QSslCertificate::fromPath(SRCDIR "more-certificates/test-cn-two-cns-cert.pem");
+ QVERIFY2(certList.count() > 0, "Please run this test from the source directory");
+
+ QStringList commonNames = certList[0].subjectInfo(QSslCertificate::CommonName);
+ QVERIFY(commonNames.contains(QString("www.example.com")));
+ QVERIFY(commonNames.contains(QString("www2.example.com")));
+}
+
+void tst_QSslCertificate::subjectAndIssuerAttributes()
+{
+ QList<QSslCertificate> certList =
+ QSslCertificate::fromPath(SRCDIR "more-certificates/test-cn-with-drink-cert.pem");
+ QVERIFY2(certList.count() > 0, "Please run this test from the source directory");
+
+ QList<QByteArray> attributes = certList[0].subjectInfoAttributes();
+ QVERIFY(attributes.contains(QByteArray("favouriteDrink")));
+ attributes.clear();
+
+ certList = QSslCertificate::fromPath(SRCDIR "more-certificates/natwest-banking.pem");
+ QVERIFY2(certList.count() > 0, "Please run this test from the source directory");
+
+ attributes = certList[0].subjectInfoAttributes();
+ QVERIFY(attributes.contains(QByteArray("1.3.6.1.4.1.311.60.2.1.3")));
+}
+
+void tst_QSslCertificate::verify()
+{
+ QList<QSslError> errors;
+ QList<QSslCertificate> toVerify;
+
+ // Like QVERIFY, but be verbose about the content of `errors' when failing
+#define VERIFY_VERBOSE(A) \
+ QVERIFY2((A), \
+ qPrintable(QString("errors: %1").arg(toString(errors))) \
+ )
+
+ // Empty chain is unspecified error
+ errors = QSslCertificate::verify(toVerify);
+ VERIFY_VERBOSE(errors.count() == 1);
+ VERIFY_VERBOSE(errors[0] == QSslError(QSslError::UnspecifiedError));
+ errors.clear();
+
+ // Verify a valid cert signed by a CA
+ QList<QSslCertificate> caCerts = QSslCertificate::fromPath(SRCDIR "verify-certs/cacert.pem");
+ QSslSocket::addDefaultCaCertificate(caCerts.first());
+
+ toVerify = QSslCertificate::fromPath(SRCDIR "verify-certs/test-ocsp-good-cert.pem");
+
+ errors = QSslCertificate::verify(toVerify);
+ VERIFY_VERBOSE(errors.count() == 0);
+ errors.clear();
+
+ // Test a blacklisted certificate
+ toVerify = QSslCertificate::fromPath(SRCDIR "verify-certs/test-addons-mozilla-org-cert.pem");
+ errors = QSslCertificate::verify(toVerify);
+ bool foundBlack = false;
+ foreach (const QSslError &error, errors) {
+ if (error.error() == QSslError::CertificateBlacklisted) {
+ foundBlack = true;
+ break;
+ }
+ }
+ QVERIFY(foundBlack);
+ errors.clear();
+
+ // This one is expired and untrusted
+ toVerify = QSslCertificate::fromPath(SRCDIR "more-certificates/cert-large-serial-number.pem");
+ errors = QSslCertificate::verify(toVerify);
+ VERIFY_VERBOSE(errors.contains(QSslError(QSslError::SelfSignedCertificate, toVerify[0])));
+ VERIFY_VERBOSE(errors.contains(QSslError(QSslError::CertificateExpired, toVerify[0])));
+ errors.clear();
+ toVerify.clear();
+
+ // This one is signed by a valid cert, but the signer is not a valid CA
+ toVerify << QSslCertificate::fromPath(SRCDIR "verify-certs/test-intermediate-not-ca-cert.pem").first();
+ toVerify << QSslCertificate::fromPath(SRCDIR "verify-certs/test-ocsp-good-cert.pem").first();
+ errors = QSslCertificate::verify(toVerify);
+ VERIFY_VERBOSE(errors.contains(QSslError(QSslError::InvalidCaCertificate, toVerify[1])));
+ toVerify.clear();
+
+ // This one is signed by a valid cert, and the signer is a valid CA
+ toVerify << QSslCertificate::fromPath(SRCDIR "verify-certs/test-intermediate-is-ca-cert.pem").first();
+ toVerify << QSslCertificate::fromPath(SRCDIR "verify-certs/test-intermediate-ca-cert.pem").first();
+ errors = QSslCertificate::verify(toVerify);
+ VERIFY_VERBOSE(errors.count() == 0);
+
+ // Recheck the above with hostname validation
+ errors = QSslCertificate::verify(toVerify, QLatin1String("example.com"));
+ VERIFY_VERBOSE(errors.count() == 0);
+
+ // Recheck the above with a bad hostname
+ errors = QSslCertificate::verify(toVerify, QLatin1String("fail.example.com"));
+ VERIFY_VERBOSE(errors.contains(QSslError(QSslError::HostNameMismatch, toVerify[0])));
+ toVerify.clear();
+
+#undef VERIFY_VERBOSE
+}
+
+QString tst_QSslCertificate::toString(const QList<QSslError>& errors)
+{
+ QStringList errorStrings;
+
+ foreach (const QSslError& error, errors) {
+ errorStrings.append(QLatin1String("\"") + error.errorString() + QLatin1String("\""));
+ }
+
+ return QLatin1String("[ ") + errorStrings.join(QLatin1String(", ")) + QLatin1String(" ]");
+}
+
+#endif // QT_NO_OPENSSL
+
+QTEST_MAIN(tst_QSslCertificate)
+#include "tst_qsslcertificate.moc"
diff --git a/tests/auto/network/ssl/qsslcertificate/verify-certs/README b/tests/auto/network/ssl/qsslcertificate/verify-certs/README
new file mode 100644
index 0000000000..87cb293ef6
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/verify-certs/README
@@ -0,0 +1,2 @@
+openssl verify -CAfile cacert.pem -untrusted test-intermediate-ca-cert.pem test-intermediate-is-ca-cert.pem
+openssl verify -CAfile cacert.pem -untrusted test-ocsp-good-cert.pem test-intermediate-not-ca-cert.pem
diff --git a/tests/auto/network/ssl/qsslcertificate/verify-certs/cacert.pem b/tests/auto/network/ssl/qsslcertificate/verify-certs/cacert.pem
new file mode 100644
index 0000000000..8c75c54bcb
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/verify-certs/cacert.pem
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIID6zCCAtOgAwIBAgIJAP4bjANFSx0BMA0GCSqGSIb3DQEBBQUAMIGrMSYwJAYD
+VQQDEx1XZXN0cG9pbnQgQ2VydGlmaWNhdGUgVGVzdCBDQTETMBEGA1UECBMKTGFu
+Y2FzaGlyZTELMAkGA1UEBhMCVUsxHTAbBgkqhkiG9w0BCQEWDmNhQGV4YW1wbGUu
+Y29tMUAwPgYDVQQKEzdXZXN0cG9pbnQgQ2VydGlmaWNhdGUgVGVzdCBSb290IENl
+cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTExMDczMTIxMDExNloXDTIxMDcyODIx
+MDExNlowgasxJjAkBgNVBAMTHVdlc3Rwb2ludCBDZXJ0aWZpY2F0ZSBUZXN0IENB
+MRMwEQYDVQQIEwpMYW5jYXNoaXJlMQswCQYDVQQGEwJVSzEdMBsGCSqGSIb3DQEJ
+ARYOY2FAZXhhbXBsZS5jb20xQDA+BgNVBAoTN1dlc3Rwb2ludCBDZXJ0aWZpY2F0
+ZSBUZXN0IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQC5xMKXviXuxFO67WzFIImO5RY3Y+dqt7maTB+p
+JiHkn98rJoBB4J1cDnEUIs5ErO+kqOjW7JwF50fePNJ5K+I6SbRVn9gxAI59ZA6O
+9UvOPZOw4/6GM24UY4B4mUcp8oXg9fhwgtjVhfXiMD2GvKQq3RazIiCoSW4aJWEq
+L58Q+sIo+jL72qwk648xIwIhuC3XzcOOE/+rCOtZmu812/NN08UfsL2qup0aaaGv
+aL36n6OIx5AYFcCD5uOxXAmUy14mhwQyDHAl6K42ghSm5b43VMMSQ+N9AQpentWl
+RH6Vt1eY52YTxjNxpRlj88GBnYxdr8WgjKOV7v8OPGXP6zWlAgMBAAGjEDAOMAwG
+A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADptDEfvsh8aq/tTc7ciGkHG
+jh7WFELVTcdWBTyveZ24298Hl9UOfsAfLqjMGMs3delAaZocchba9Og2xSZyRstH
+GUtlJXd4PnSJSx/TksPf2DCANo5sxBWBITs1Iprm3Nlm3/xPZM2QLIamRYi2J6Ed
+JTfWvMpoaW1umJX49jKqk1gfdcS6eUSaXetgYP2FQV7DstqPLYfQ731nEXZ1LXFM
+PO7IoPccqk4YJ0KOV7hFb7NCq4a6cz/Gf0S0qJ44vqHz6iRZpmWIo5UFivwtLw9r
+iMbdJ1mCCMR0oN5om3muKc7Sz+l2ItxdYMcLkZ1/3ouvQqOX+qIOrYEUN1RZCzI=
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/verify-certs/test-addons-mozilla-org-cert.pem b/tests/auto/network/ssl/qsslcertificate/verify-certs/test-addons-mozilla-org-cert.pem
new file mode 100644
index 0000000000..07123e8577
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/verify-certs/test-addons-mozilla-org-cert.pem
@@ -0,0 +1,34 @@
+-----BEGIN CERTIFICATE-----
+MIIF+DCCBOCgAwIBAgIRAJI51TSPQNFpWnRUcOHyP0MwDQYJKoZIhvcNAQEFBQAw
+gZcxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtl
+IENpdHkxHjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8GA1UECxMY
+aHR0cDovL3d3dy51c2VydHJ1c3QuY29tMR8wHQYDVQQDExZVVE4tVVNFUkZpcnN0
+LUhhcmR3YXJlMB4XDTExMDMxNTAwMDAwMFoXDTE0MDMxNDIzNTk1OVowgeIxCzAJ
+BgNVBAYTAlVTMQ4wDAYDVQQREwUzODQ3NzEQMA4GA1UECBMHRmxvcmlkYTEQMA4G
+A1UEBxMHRW5nbGlzaDEXMBUGA1UECRMOU2VhIFZpbGxhZ2UgMTAxFDASBgNVBAoT
+C0dvb2dsZSBMdGQuMRMwEQYDVQQLEwpUZWNoIERlcHQuMSgwJgYDVQQLEx9Ib3N0
+ZWQgYnkgR1RJIEdyb3VwIENvcnBvcmF0aW9uMRQwEgYDVQQLEwtQbGF0aW51bVNT
+TDEbMBkGA1UEAxMSYWRkb25zLm1vemlsbGEub3JnMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAq8ZtNvMVc3iDc850hdWu7LLw4CQfE4O4IKy7mv6Iu6uh
+HQsfRQCqSbc1Nwxq70dMudG+41cSBI2Sx7bsAby22seBOCCtcoXmDvyBbAetaHY4
+xUTXzMZKxZc+ZPRR5vB+suxW9yWCTUmYyxaY3SPxiZHRF5dAmSbW4qIrXt+9ifIb
+GlMtzFBBetA9KgxVcBQB6VhJEHoLk4KL4R7tOoAQgs6WijTwzNfTubRQh1VUCbid
+QihVAOWMNVS/3SWRRrcN5V2DqOWL+4TkPK522sRDK1t0C/i+XWjxeFu1zn3xXZlA
+2sruOIFQvpihbLgkrfOvjA/XESgshBhMfbXZjzC1GwIDAQABo4IB8DCCAewwHwYD
+VR0jBBgwFoAUoXJfJhsomEOVXQc31YWWnUvSw0UwHQYDVR0OBBYEFN2A0lQ990xw
+yqOw3TR6MuToO1o7MA4GA1UdDwEB/wQEAwIFoDAMBgNVHRMBAf8EAjAAMB0GA1Ud
+JQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBGBgNVHSAEPzA9MDsGDCsGAQQBsjEB
+AgEDBDArMCkGCCsGAQUFBwIBFh1odHRwczovL3NlY3VyZS5jb21vZG8uY29tL0NQ
+UzB7BgNVHR8EdDByMDigNqA0hjJodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9VVE4t
+VVNFUkZpcnN0LUhhcmR3YXJlLmNybDA2oDSgMoYwaHR0cDovL2NybC5jb21vZG8u
+bmV0L1VUTi1VU0VSRmlyc3QtSGFyZHdhcmUuY3JsMHEGCCsGAQUFBwEBBGUwYzA7
+BggrBgEFBQcwAoYvaHR0cDovL2NydC5jb21vZG9jYS5jb20vVVROQWRkVHJ1c3RT
+ZXJ2ZXJDQS5jcnQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmNvbW9kb2NhLmNv
+bTA1BgNVHREELjAsghJhZGRvbnMubW96aWxsYS5vcmeCFnd3dy5hZGRvbnMubW96
+aWxsYS5vcmcwDQYJKoZIhvcNAQEFBQADggEBADM7YxX8sewULJPddZTegVrZTpm+
++0qkOVVNoUB63hMqh6k3z+jV+63Re21vjCCHglTmV0m8ICiEzdYB2ZOLF24jZuWE
+yIA/xqFwgOTsTR35/JFac2IpmvcgHGHgizmfyrx+jd282bHjn57fFVORIVIL2Roj
+D2Y226yTlkqjpSLPKfeimaj2ttlArtl+tvZYLpusNspkj2VS3IacgqtuUEvaX/oF
+AIgwDt6NVr+BR409BuKyYpJnj57ImrLlBrhwJLh3fCMKOMN5CNixUZ2slRHHQBee
+oxyP8hGnaCfaSQWEGHxYLQFnXOWfoSm7SjlFL78Rqnmi7bTUtWVDt5NGitM=
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/verify-certs/test-intermediate-ca-cert.pem b/tests/auto/network/ssl/qsslcertificate/verify-certs/test-intermediate-ca-cert.pem
new file mode 100644
index 0000000000..d00490caba
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/verify-certs/test-intermediate-ca-cert.pem
@@ -0,0 +1,66 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 28 (0x1c)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: CN=Westpoint Certificate Test CA, ST=Lancashire, C=UK/emailAddress=ca@example.com, O=Westpoint Certificate Test Root Certification Authority
+ Validity
+ Not Before: Jul 31 21:01:18 2011 GMT
+ Not After : Jul 28 21:01:18 2021 GMT
+ Subject: ST=Lancashire, C=UK/emailAddress=test@example.com, O=Test intermediate CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:bc:bd:83:c1:bc:36:d8:9c:74:68:5a:46:48:25:
+ 83:59:f8:35:1e:8f:dc:2c:52:3b:7c:2e:ea:40:c4:
+ 93:b6:39:31:df:f5:a6:f8:01:17:67:93:21:59:9b:
+ 89:7f:ed:2a:19:7b:25:a5:e1:71:12:99:e5:14:28:
+ df:75:b5:17:1c:3b:1d:3d:74:48:4f:b7:42:f4:3a:
+ ab:56:05:2b:fc:d3:27:97:01:08:5b:ad:26:9b:f2:
+ 87:51:9c:7e:e1:f1:ef:1c:bf:ad:7e:38:d9:76:89:
+ 30:a6:8c:2f:6f:87:9f:9e:57:13:14:b4:45:30:f3:
+ be:58:df:8a:d2:ee:7b:1d:89
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ Authority Information Access:
+ OCSP - URI:http://ocsp.example.com:8888/
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 33:84:9d:0e:b2:59:04:dc:ef:e3:04:8b:00:6c:64:ea:58:9e:
+ 36:59:76:27:59:a0:b8:ee:0d:86:83:ff:db:65:eb:6c:1f:16:
+ 47:e7:f5:e6:c3:88:81:73:7e:ed:12:8d:7e:fd:5e:b1:5c:68:
+ 47:f8:f9:ca:e3:e0:c0:f3:12:b2:24:3b:77:2c:98:de:05:6d:
+ a8:ec:27:b8:af:ab:84:25:26:73:b4:58:4c:7c:c1:74:97:98:
+ ab:0e:e6:99:70:bc:38:b0:9a:e3:d9:5c:75:fa:46:d2:87:55:
+ 09:86:8f:ef:4a:e4:ef:3e:32:c6:ac:9d:27:86:29:b8:78:38:
+ 7b:87:6c:57:72:bd:57:99:73:36:db:fa:52:bd:7b:a7:05:cd:
+ 28:b8:85:fc:11:47:5e:c6:77:72:6a:fb:73:3e:8b:a4:6d:f8:
+ 17:f4:12:d5:36:e0:ef:5c:f8:b2:a1:69:3e:4c:cf:86:5f:63:
+ f6:02:60:95:7f:61:e8:cb:7f:14:66:da:36:2e:78:13:3e:68:
+ ae:3f:13:c1:79:88:18:18:3f:23:f3:9a:e1:e7:7e:ae:50:e4:
+ b7:80:76:31:92:74:79:2c:de:d0:74:fe:81:7c:f6:01:14:6a:
+ 1f:5f:88:85:6a:11:1d:50:af:f1:97:4d:67:40:c3:e9:ae:6f:
+ 60:e2:bc:e2
+-----BEGIN CERTIFICATE-----
+MIIDUDCCAjigAwIBAgIBHDANBgkqhkiG9w0BAQUFADCBqzEmMCQGA1UEAxMdV2Vz
+dHBvaW50IENlcnRpZmljYXRlIFRlc3QgQ0ExEzARBgNVBAgTCkxhbmNhc2hpcmUx
+CzAJBgNVBAYTAlVLMR0wGwYJKoZIhvcNAQkBFg5jYUBleGFtcGxlLmNvbTFAMD4G
+A1UEChM3V2VzdHBvaW50IENlcnRpZmljYXRlIFRlc3QgUm9vdCBDZXJ0aWZpY2F0
+aW9uIEF1dGhvcml0eTAeFw0xMTA3MzEyMTAxMThaFw0yMTA3MjgyMTAxMThaMGIx
+EzARBgNVBAgTCkxhbmNhc2hpcmUxCzAJBgNVBAYTAlVLMR8wHQYJKoZIhvcNAQkB
+FhB0ZXN0QGV4YW1wbGUuY29tMR0wGwYDVQQKExRUZXN0IGludGVybWVkaWF0ZSBD
+QTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAvL2Dwbw22Jx0aFpGSCWDWfg1
+Ho/cLFI7fC7qQMSTtjkx3/Wm+AEXZ5MhWZuJf+0qGXslpeFxEpnlFCjfdbUXHDsd
+PXRIT7dC9DqrVgUr/NMnlwEIW60mm/KHUZx+4fHvHL+tfjjZdokwpowvb4efnlcT
+FLRFMPO+WN+K0u57HYkCAwEAAaNLMEkwOQYIKwYBBQUHAQEELTArMCkGCCsGAQUF
+BzABhh1odHRwOi8vb2NzcC5leGFtcGxlLmNvbTo4ODg4LzAMBgNVHRMEBTADAQH/
+MA0GCSqGSIb3DQEBBQUAA4IBAQAzhJ0OslkE3O/jBIsAbGTqWJ42WXYnWaC47g2G
+g//bZetsHxZH5/Xmw4iBc37tEo1+/V6xXGhH+PnK4+DA8xKyJDt3LJjeBW2o7Ce4
+r6uEJSZztFhMfMF0l5irDuaZcLw4sJrj2Vx1+kbSh1UJho/vSuTvPjLGrJ0nhim4
+eDh7h2xXcr1XmXM22/pSvXunBc0ouIX8EUdexndyavtzPoukbfgX9BLVNuDvXPiy
+oWk+TM+GX2P2AmCVf2Hoy38UZto2LngTPmiuPxPBeYgYGD8j85rh536uUOS3gHYx
+knR5LN7QdP6BfPYBFGofX4iFahEdUK/xl01nQMPprm9g4rzi
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/verify-certs/test-intermediate-is-ca-cert.pem b/tests/auto/network/ssl/qsslcertificate/verify-certs/test-intermediate-is-ca-cert.pem
new file mode 100644
index 0000000000..396cad86cb
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/verify-certs/test-intermediate-is-ca-cert.pem
@@ -0,0 +1,53 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 29 (0x1d)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: ST=Lancashire, C=UK/emailAddress=test@example.com, O=Test intermediate CA
+ Validity
+ Not Before: Jul 31 21:01:18 2011 GMT
+ Not After : Jul 28 21:01:18 2021 GMT
+ Subject: CN=example.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:c9:bb:98:5b:27:cd:b1:8a:a9:38:fc:aa:bb:ad:
+ a1:ed:cb:94:94:3e:79:90:ae:35:f3:87:b1:2a:4e:
+ d5:ff:55:93:e0:1a:68:2a:36:94:05:38:a7:72:64:
+ a3:31:0f:61:5c:ec:76:41:f1:35:4a:5e:bc:ef:51:
+ 90:9e:33:b4:08:7a:3f:f0:04:a8:46:99:96:25:b3:
+ 03:c8:cd:8c:33:42:76:82:b9:db:61:c6:91:ed:76:
+ 86:ae:04:38:d7:e5:5c:a9:a9:f9:b6:13:f4:90:40:
+ 6d:ec:2f:ba:ed:bc:ff:88:05:f0:7b:c8:ac:bd:d0:
+ 72:3a:91:64:86:06:89:66:0d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Authority Information Access:
+ OCSP - URI:http://ocsp.example.com:8888/
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 22:30:97:01:ea:d0:a8:d8:b5:32:97:c8:c9:8b:7d:01:02:53:
+ 74:f8:0a:10:dc:fc:73:b2:50:bb:59:47:f3:e4:9f:44:94:d5:
+ ca:c0:64:da:83:00:95:43:15:a5:e3:30:ce:66:ca:55:8c:16:
+ 03:1e:55:02:8b:c7:ad:ed:2e:ae:ee:31:59:53:37:ff:26:86:
+ 93:9d:e2:69:2e:c0:2a:66:38:a5:b5:54:a1:02:0a:83:67:e0:
+ 91:cf:fc:09:c3:70:71:b6:cf:fc:d3:e9:9f:f5:1c:4d:55:ec:
+ 66:f7:07:71:fc:d6:17:de:e1:ab:e6:f2:7b:83:46:1e:b9:96:
+ 95:8f
+-----BEGIN CERTIFICATE-----
+MIICNjCCAZ+gAwIBAgIBHTANBgkqhkiG9w0BAQUFADBiMRMwEQYDVQQIEwpMYW5j
+YXNoaXJlMQswCQYDVQQGEwJVSzEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFtcGxl
+LmNvbTEdMBsGA1UEChMUVGVzdCBpbnRlcm1lZGlhdGUgQ0EwHhcNMTEwNzMxMjEw
+MTE4WhcNMjEwNzI4MjEwMTE4WjAWMRQwEgYDVQQDEwtleGFtcGxlLmNvbTCBnzAN
+BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAybuYWyfNsYqpOPyqu62h7cuUlD55kK41
+84exKk7V/1WT4BpoKjaUBTincmSjMQ9hXOx2QfE1Sl6871GQnjO0CHo/8ASoRpmW
+JbMDyM2MM0J2grnbYcaR7XaGrgQ41+Vcqan5thP0kEBt7C+67bz/iAXwe8isvdBy
+OpFkhgaJZg0CAwEAAaNIMEYwCQYDVR0TBAIwADA5BggrBgEFBQcBAQQtMCswKQYI
+KwYBBQUHMAGGHWh0dHA6Ly9vY3NwLmV4YW1wbGUuY29tOjg4ODgvMA0GCSqGSIb3
+DQEBBQUAA4GBACIwlwHq0KjYtTKXyMmLfQECU3T4ChDc/HOyULtZR/Pkn0SU1crA
+ZNqDAJVDFaXjMM5mylWMFgMeVQKLx63tLq7uMVlTN/8mhpOd4mkuwCpmOKW1VKEC
+CoNn4JHP/AnDcHG2z/zT6Z/1HE1V7Gb3B3H81hfe4avm8nuDRh65lpWP
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/verify-certs/test-intermediate-not-ca-cert.pem b/tests/auto/network/ssl/qsslcertificate/verify-certs/test-intermediate-not-ca-cert.pem
new file mode 100644
index 0000000000..34ad2b10a8
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/verify-certs/test-intermediate-not-ca-cert.pem
@@ -0,0 +1,54 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 27 (0x1b)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: CN=example.com, ST=Lancashire, C=UK/emailAddress=test@example.com, O=Some organisation
+ Validity
+ Not Before: Jul 31 21:01:18 2011 GMT
+ Not After : Jul 28 21:01:18 2021 GMT
+ Subject: CN=example.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:ea:d6:97:b5:3c:f4:37:8a:58:b4:7a:49:31:55:
+ dd:c8:84:ee:36:f6:72:3a:31:99:d1:df:af:bb:f9:
+ 17:e9:d8:47:d2:20:4b:94:ce:ea:c1:6b:23:9a:da:
+ 02:41:29:51:34:05:13:c0:98:4d:87:f8:91:a8:85:
+ 81:e4:ab:26:3d:26:59:29:16:7d:04:db:57:7b:f0:
+ b6:2b:5d:cf:e7:82:ba:83:a7:bc:63:43:03:2a:2b:
+ 18:40:89:4c:1e:90:bc:bf:10:24:81:50:0d:2e:e8:
+ 8e:a9:0a:fc:f8:cd:97:98:3c:cc:55:b7:f2:b2:0d:
+ 0e:36:53:3a:b2:d0:45:90:8b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Authority Information Access:
+ OCSP - URI:http://ocsp.example.com:8888/
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 82:d8:53:9c:d8:0b:0a:b3:9d:b4:0a:9f:93:ec:96:a6:31:6b:
+ 79:c9:d2:1c:76:0b:b7:f3:9f:b9:7a:dd:d7:b7:7b:26:ba:0a:
+ 54:2a:a3:ad:89:8e:3c:b8:8e:ea:09:53:58:73:9a:b3:a0:40:
+ 90:02:f2:60:04:b8:f0:2a:61:bd:91:9b:5e:81:5f:bf:cc:f2:
+ 33:33:8a:70:07:f5:ea:c0:05:38:34:f7:dc:ea:0c:74:01:5d:
+ dd:92:ab:f2:87:64:1b:7c:be:ae:37:c1:6c:ae:99:73:a5:aa:
+ 45:20:32:57:19:cb:30:45:61:2c:3b:23:52:ee:f0:cc:12:80:
+ 97:34
+-----BEGIN CERTIFICATE-----
+MIICSTCCAbKgAwIBAgIBGzANBgkqhkiG9w0BAQUFADB1MRQwEgYDVQQDEwtleGFt
+cGxlLmNvbTETMBEGA1UECBMKTGFuY2FzaGlyZTELMAkGA1UEBhMCVUsxHzAdBgkq
+hkiG9w0BCQEWEHRlc3RAZXhhbXBsZS5jb20xGjAYBgNVBAoTEVNvbWUgb3JnYW5p
+c2F0aW9uMB4XDTExMDczMTIxMDExOFoXDTIxMDcyODIxMDExOFowFjEUMBIGA1UE
+AxMLZXhhbXBsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOrWl7U8
+9DeKWLR6STFV3ciE7jb2cjoxmdHfr7v5F+nYR9IgS5TO6sFrI5raAkEpUTQFE8CY
+TYf4kaiFgeSrJj0mWSkWfQTbV3vwtitdz+eCuoOnvGNDAyorGECJTB6QvL8QJIFQ
+DS7ojqkK/PjNl5g8zFW38rINDjZTOrLQRZCLAgMBAAGjSDBGMAkGA1UdEwQCMAAw
+OQYIKwYBBQUHAQEELTArMCkGCCsGAQUFBzABhh1odHRwOi8vb2NzcC5leGFtcGxl
+LmNvbTo4ODg4LzANBgkqhkiG9w0BAQUFAAOBgQCC2FOc2AsKs520Cp+T7JamMWt5
+ydIcdgu385+5et3Xt3smugpUKqOtiY48uI7qCVNYc5qzoECQAvJgBLjwKmG9kZte
+gV+/zPIzM4pwB/XqwAU4NPfc6gx0AV3dkqvyh2QbfL6uN8FsrplzpapFIDJXGcsw
+RWEsOyNS7vDMEoCXNA==
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcertificate/verify-certs/test-ocsp-good-cert.pem b/tests/auto/network/ssl/qsslcertificate/verify-certs/test-ocsp-good-cert.pem
new file mode 100644
index 0000000000..34b26c6d5e
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcertificate/verify-certs/test-ocsp-good-cert.pem
@@ -0,0 +1,67 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: CN=Westpoint Certificate Test CA, ST=Lancashire, C=UK/emailAddress=ca@example.com, O=Westpoint Certificate Test Root Certification Authority
+ Validity
+ Not Before: Jul 31 21:01:16 2011 GMT
+ Not After : Jul 28 21:01:16 2021 GMT
+ Subject: CN=example.com, ST=Lancashire, C=UK/emailAddress=test@example.com, O=Some organisation
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (1024 bit)
+ Modulus:
+ 00:97:c9:92:27:81:a7:4c:64:82:a2:30:d6:07:b7:
+ 57:e0:9c:ea:cd:eb:53:be:ea:b6:b5:47:66:d0:68:
+ 54:25:a7:ed:21:5c:dc:fd:da:41:f6:c7:c0:35:ae:
+ 97:72:fd:8b:af:29:3d:38:5a:67:8b:39:8a:ce:86:
+ 25:0f:38:a7:b5:38:b3:8e:81:f0:ea:79:99:cb:f5:
+ 23:64:55:f3:4b:a4:b6:23:64:29:ea:ba:f3:29:52:
+ a7:7f:32:dc:0d:b6:d9:d4:e6:13:de:01:41:86:9a:
+ 2d:8f:bb:0c:18:88:09:ac:d4:6a:e9:cb:8a:17:8a:
+ 85:09:a6:ae:a6:1c:05:e9:55
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Authority Information Access:
+ OCSP - URI:http://ocsp.example.com:8888/
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 8b:9b:96:fb:8e:1b:77:f5:70:39:fe:76:51:ac:a9:6b:80:a5:
+ b7:95:8b:c3:1a:9c:1f:bb:d1:d1:68:43:40:96:62:d6:a6:da:
+ d9:fd:9d:9a:9e:8a:84:fa:f5:54:ce:a8:d7:37:c7:0c:95:fc:
+ 11:8b:e9:32:53:e5:59:61:0a:53:70:f3:d6:ed:3f:b1:f4:49:
+ bf:86:c1:77:0d:b1:ac:65:7e:62:d2:f2:5a:31:50:a7:ed:28:
+ bb:63:d5:f3:4f:43:3a:3f:bf:3b:d0:94:aa:a1:74:95:be:a4:
+ 0f:8b:e0:6f:d8:33:84:76:71:b2:da:f4:0e:1e:d2:eb:f0:c3:
+ 1e:33:79:21:35:93:18:05:38:db:63:85:1a:e4:84:41:0a:c3:
+ fb:fd:5c:69:3d:18:0a:38:b8:16:18:d3:23:b9:51:47:2e:54:
+ 08:d1:fc:2e:b6:63:62:78:9c:26:59:c2:5e:5a:38:76:47:e7:
+ f0:f8:7b:b7:00:46:34:b0:44:28:a9:33:d7:e5:1d:52:c8:fb:
+ 32:a5:25:86:21:0c:80:f0:4b:37:60:a0:45:69:9f:6b:b0:34:
+ 91:5e:4c:62:45:99:83:1d:80:48:78:bb:ee:d4:83:39:76:c3:
+ e6:fb:31:e9:20:f0:64:90:24:4e:c6:07:75:40:1f:7e:97:77:
+ 1f:bf:a2:ef
+-----BEGIN CERTIFICATE-----
+MIIDYDCCAkigAwIBAgIBATANBgkqhkiG9w0BAQUFADCBqzEmMCQGA1UEAxMdV2Vz
+dHBvaW50IENlcnRpZmljYXRlIFRlc3QgQ0ExEzARBgNVBAgTCkxhbmNhc2hpcmUx
+CzAJBgNVBAYTAlVLMR0wGwYJKoZIhvcNAQkBFg5jYUBleGFtcGxlLmNvbTFAMD4G
+A1UEChM3V2VzdHBvaW50IENlcnRpZmljYXRlIFRlc3QgUm9vdCBDZXJ0aWZpY2F0
+aW9uIEF1dGhvcml0eTAeFw0xMTA3MzEyMTAxMTZaFw0yMTA3MjgyMTAxMTZaMHUx
+FDASBgNVBAMTC2V4YW1wbGUuY29tMRMwEQYDVQQIEwpMYW5jYXNoaXJlMQswCQYD
+VQQGEwJVSzEfMB0GCSqGSIb3DQEJARYQdGVzdEBleGFtcGxlLmNvbTEaMBgGA1UE
+ChMRU29tZSBvcmdhbmlzYXRpb24wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGB
+AJfJkieBp0xkgqIw1ge3V+Cc6s3rU77qtrVHZtBoVCWn7SFc3P3aQfbHwDWul3L9
+i68pPThaZ4s5is6GJQ84p7U4s46B8Op5mcv1I2RV80uktiNkKeq68ylSp38y3A22
+2dTmE94BQYaaLY+7DBiICazUaunLiheKhQmmrqYcBelVAgMBAAGjSDBGMAkGA1Ud
+EwQCMAAwOQYIKwYBBQUHAQEELTArMCkGCCsGAQUFBzABhh1odHRwOi8vb2NzcC5l
+eGFtcGxlLmNvbTo4ODg4LzANBgkqhkiG9w0BAQUFAAOCAQEAi5uW+44bd/VwOf52
+Uaypa4Clt5WLwxqcH7vR0WhDQJZi1qba2f2dmp6KhPr1VM6o1zfHDJX8EYvpMlPl
+WWEKU3Dz1u0/sfRJv4bBdw2xrGV+YtLyWjFQp+0ou2PV809DOj+/O9CUqqF0lb6k
+D4vgb9gzhHZxstr0Dh7S6/DDHjN5ITWTGAU422OFGuSEQQrD+/1caT0YCji4FhjT
+I7lRRy5UCNH8LrZjYnicJlnCXlo4dkfn8Ph7twBGNLBEKKkz1+UdUsj7MqUlhiEM
+gPBLN2CgRWmfa7A0kV5MYkWZgx2ASHi77tSDOXbD5vsx6SDwZJAkTsYHdUAffpd3
+H7+i7w==
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslcipher/.gitignore b/tests/auto/network/ssl/qsslcipher/.gitignore
new file mode 100644
index 0000000000..13137ce3aa
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcipher/.gitignore
@@ -0,0 +1 @@
+tst_qsslcipher
diff --git a/tests/auto/network/ssl/qsslcipher/qsslcipher.pro b/tests/auto/network/ssl/qsslcipher/qsslcipher.pro
new file mode 100644
index 0000000000..78fd387069
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcipher/qsslcipher.pro
@@ -0,0 +1,18 @@
+load(qttest_p4)
+
+SOURCES += tst_qsslcipher.cpp
+!wince*:win32:LIBS += -lws2_32
+QT = core network
+
+TARGET = tst_qsslcipher
+
+win32 {
+ CONFIG(debug, debug|release) {
+ DESTDIR = debug
+} else {
+ DESTDIR = release
+ }
+}
+
+symbian: TARGET.CAPABILITY = NetworkServices
+
diff --git a/tests/auto/network/ssl/qsslcipher/tst_qsslcipher.cpp b/tests/auto/network/ssl/qsslcipher/tst_qsslcipher.cpp
new file mode 100644
index 0000000000..5fe4d03bdd
--- /dev/null
+++ b/tests/auto/network/ssl/qsslcipher/tst_qsslcipher.cpp
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qsslcipher.h>
+
+#include <QtNetwork/qhostaddress.h>
+#include <QtNetwork/qnetworkproxy.h>
+
+class tst_QSslCipher : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QSslCipher();
+ virtual ~tst_QSslCipher();
+
+public slots:
+ void initTestCase_data();
+ void init();
+ void cleanup();
+
+#ifndef QT_NO_OPENSSL
+
+private slots:
+ void constructing();
+
+#endif
+};
+
+tst_QSslCipher::tst_QSslCipher()
+{
+}
+
+tst_QSslCipher::~tst_QSslCipher()
+{
+
+}
+
+void tst_QSslCipher::initTestCase_data()
+{
+}
+
+void tst_QSslCipher::init()
+{
+}
+
+void tst_QSslCipher::cleanup()
+{
+}
+
+#ifndef QT_NO_OPENSSL
+
+void tst_QSslCipher::constructing()
+{
+ QSslCipher cipher;
+}
+
+#endif // QT_NO_OPENSSL
+
+QTEST_MAIN(tst_QSslCipher)
+#include "tst_qsslcipher.moc"
diff --git a/tests/auto/network/ssl/qsslerror/.gitignore b/tests/auto/network/ssl/qsslerror/.gitignore
new file mode 100644
index 0000000000..e30995e94a
--- /dev/null
+++ b/tests/auto/network/ssl/qsslerror/.gitignore
@@ -0,0 +1 @@
+tst_qsslerror
diff --git a/tests/auto/network/ssl/qsslerror/qsslerror.pro b/tests/auto/network/ssl/qsslerror/qsslerror.pro
new file mode 100644
index 0000000000..5b907fb600
--- /dev/null
+++ b/tests/auto/network/ssl/qsslerror/qsslerror.pro
@@ -0,0 +1,18 @@
+load(qttest_p4)
+
+SOURCES += tst_qsslerror.cpp
+!wince*:win32:LIBS += -lws2_32
+QT = core network
+
+TARGET = tst_qsslerror
+
+win32 {
+ CONFIG(debug, debug|release) {
+ DESTDIR = debug
+} else {
+ DESTDIR = release
+ }
+}
+
+symbian: TARGET.CAPABILITY = NetworkServices
+
diff --git a/tests/auto/network/ssl/qsslerror/tst_qsslerror.cpp b/tests/auto/network/ssl/qsslerror/tst_qsslerror.cpp
new file mode 100644
index 0000000000..3fae88ec00
--- /dev/null
+++ b/tests/auto/network/ssl/qsslerror/tst_qsslerror.cpp
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qsslerror.h>
+
+#include <QtNetwork/qhostaddress.h>
+#include <QtNetwork/qnetworkproxy.h>
+
+class tst_QSslError : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QSslError();
+ virtual ~tst_QSslError();
+
+ static void enterLoop(int secs)
+ {
+ ++loopLevel;
+ QTestEventLoop::instance().enterLoop(secs);
+ --loopLevel;
+ }
+ static void exitLoop()
+ {
+ // Safe exit - if we aren't in an event loop, don't
+ // exit one.
+ if (loopLevel > 0)
+ QTestEventLoop::instance().exitLoop();
+ }
+ static bool timeout()
+ {
+ return QTestEventLoop::instance().timeout();
+ }
+
+public slots:
+ void initTestCase_data();
+ void init();
+ void cleanup();
+
+#ifndef QT_NO_OPENSSL
+private slots:
+ void constructing();
+#endif
+
+private:
+ static int loopLevel;
+};
+
+int tst_QSslError::loopLevel = 0;
+
+tst_QSslError::tst_QSslError()
+{
+}
+
+tst_QSslError::~tst_QSslError()
+{
+
+}
+
+void tst_QSslError::initTestCase_data()
+{
+}
+
+void tst_QSslError::init()
+{
+}
+
+void tst_QSslError::cleanup()
+{
+}
+
+#ifndef QT_NO_OPENSSL
+
+void tst_QSslError::constructing()
+{
+ QSslError error;
+}
+
+#endif // QT_NO_OPENSSL
+
+QTEST_MAIN(tst_QSslError)
+#include "tst_qsslerror.moc"
diff --git a/tests/auto/network/ssl/qsslkey/.gitignore b/tests/auto/network/ssl/qsslkey/.gitignore
new file mode 100644
index 0000000000..7c9a790dd7
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/.gitignore
@@ -0,0 +1 @@
+tst_qsslkey
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-1024.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-1024.der
new file mode 100644
index 0000000000..5b4026bef3
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-1024.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-1024.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-1024.pem
new file mode 100644
index 0000000000..cdb16c3841
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-1024.pem
@@ -0,0 +1,12 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBuwIBAAKBgQDBDNxGlo12UTCZ4S5XxcfQ8pKaYMaPYCpcJqbRMQ89VshZPFus
+ZycnITHQ3fjhHyxPfXFwzKFh9cxvJTGyWmazQBj4YOG09DzPs3fvRiIz5zu1bdJ0
+rH0VJNKdbDmdDH2BKssPrqIjQoLNwjQLcE5Ddg2as8dfg6pPi7QVq2+U6wIVAMMh
+a50lRJAJckZuztWEkV4I7H03AoGAfRXSIMUWvfnwLIDuuThj5KhFKML0kd0BxrT9
+H0dICi4pTv7DyH7OWhrCS/025aK/AehrfU+QSiceUPxZLSxeyisSgtxWIolp8zgj
+1hBPUW/lpMwNgChoKf8EgagHHY4Y0+eLnL7D/5M4hBX9eQLhK3tvaULbkW4pjR+r
+nYW9UEMCgYAhRYQ296sCvQlqjhTyj8/VFahXvXnV2YuQ/2QFm0KHXbRXsmR2ectw
+NcaBvD87EZ3KRXQiSXzea6WycOw9YXcTmgzLUefHaBkQ38973pmPIrO91HDJqVE0
+GLOIIbh796Y/9z7//BO4yAXQO9jcxeFKwiB2zYluZOVDOiFFgqqbMgIVAK0dcUpb
+9EOsRsRdOVI3hIxssc71
+-----END DSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512.der
new file mode 100644
index 0000000000..0fc977f4e4
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512.pem
new file mode 100644
index 0000000000..35210e4dec
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-512.pem
@@ -0,0 +1,8 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIH4AgEAAkEA2tY9+lNVCnDx//ciofnvm/OPWi7oMQ6XFFfXrpjltIG+9eRQv0j4
+SqcwHpsqcaC4vjsbHFTDR0p8UyUAbrXzLwIVAOKRP6SgXHveEJ//aztaVltEWqBB
+AkAj1tdgG3FQBxG5UJQGl53XsOOBJ9xz21RrrrlkqCO9G9ClNjmQ1XzrkBHije1M
+Pb6iOLH1aPYiY6svkxaDMb88AkEAzobcabWo6sag70paK/ihZlSbd4EC5Hl1XjtC
+5sKFBkjLK3A79f9TobAwDiHzSxdiLNT0xKd+iOKoWZnAj+TJ2AIUI7+wILGkcyW7
+nb4wf7r1HYIo8bk=
+-----END DSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-576.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-576.der
new file mode 100644
index 0000000000..30cea46c1e
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-576.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-576.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-576.pem
new file mode 100644
index 0000000000..a398ddcf13
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-576.pem
@@ -0,0 +1,8 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBDwIBAAJJANeKU0IdVgDc/dVL6vrEjgZW8lMLrUyjYDhu65sl8LaOmamwvozx
+ISFjYaeIMPCloHnn2jijsjQpjnlj5rVRT1MYWt2i56jV+wIVANvg9uDO7mNdcuOW
+uT+xveysakC9Akg2q1Vi56KzKVR4T2KIS4yTH3bz2wwiWd80p+SylyOkM/fSIrxJ
+IRYGugR1WY7lgWAI8E0mJDXKmajpGSvysDHnjdlSpSVSUNICSD9wBxobS/ySpKs+
+ks11XCPyZiMsf+LjUtT7nK5RBTG0PDEw+82MchouPc4YUPGR+Qf64GB7AxBYQpt/
+YhLXtFVCocZUt0HJBwIUHhfcQUujc40YUkOYavxrU+1eQUY=
+-----END DSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-960.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-960.der
new file mode 100644
index 0000000000..d8291b87ca
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-960.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pri-960.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-960.pem
new file mode 100644
index 0000000000..054c174ecf
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pri-960.pem
@@ -0,0 +1,11 @@
+-----BEGIN DSA PRIVATE KEY-----
+MIIBnwIBAAJ5AMDmMbjPuQOJOd57ZBya8tICsSbRGo+yStRm0rubqAnjKzgMOZc8
+CWT+/2ddVYKuQCzG0DEYeGyBxGUSP2Z7TQrVJ/4GmHLeHJIiIBT8JAh+yHmDWhNO
+sKZbsUtsckwBEuh/1vs++L+PX8QGvHCE6Y+sFTR6xCs6EQIVAO/gigt7sEp3MzIh
+cFGLiT6PlbNNAnh+GFk2cJecrMbpw3dT5ilTPZkWm8nyC/1fJwVk4dEdY7yjAnCX
+Su1eO1m6RLM/OlVXMT84HKaqA95w09dg8s9LmlrKR5ROH6MXYoOweowFcd/PrJd7
+U3sGRN7cwzVEW8/PZODYJY0Ab0bhpjQYeMObQf61t3iREbUCeB6KXt9DouH7ccWX
+keJM0Uf+eXCxPbnMwMsR6ae3F2G/YNlarqkKI3CpuwcKI1Hvq3iitznPPmZJrqlG
+ywI+es5axqskbV/7NY6VcwaHVR3FcdSpksxCuG5zP3GEqVS7b3WPj98jBGMb0VB4
+CtK6CpxjC283/Yuy8QIUdyj4ssD0ezN3bhOJtr3fBGWjX6k=
+-----END DSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pub-1024.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pub-1024.der
new file mode 100644
index 0000000000..efff9d27c3
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pub-1024.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pub-1024.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pub-1024.pem
new file mode 100644
index 0000000000..f39bc37814
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pub-1024.pem
@@ -0,0 +1,12 @@
+-----BEGIN PUBLIC KEY-----
+MIIBtjCCASsGByqGSM44BAEwggEeAoGBAMEM3EaWjXZRMJnhLlfFx9Dykppgxo9g
+KlwmptExDz1WyFk8W6xnJychMdDd+OEfLE99cXDMoWH1zG8lMbJaZrNAGPhg4bT0
+PM+zd+9GIjPnO7Vt0nSsfRUk0p1sOZ0MfYEqyw+uoiNCgs3CNAtwTkN2DZqzx1+D
+qk+LtBWrb5TrAhUAwyFrnSVEkAlyRm7O1YSRXgjsfTcCgYB9FdIgxRa9+fAsgO65
+OGPkqEUowvSR3QHGtP0fR0gKLilO/sPIfs5aGsJL/Tblor8B6Gt9T5BKJx5Q/Fkt
+LF7KKxKC3FYiiWnzOCPWEE9Rb+WkzA2AKGgp/wSBqAcdjhjT54ucvsP/kziEFf15
+AuEre29pQtuRbimNH6udhb1QQwOBhAACgYAhRYQ296sCvQlqjhTyj8/VFahXvXnV
+2YuQ/2QFm0KHXbRXsmR2ectwNcaBvD87EZ3KRXQiSXzea6WycOw9YXcTmgzLUefH
+aBkQ38973pmPIrO91HDJqVE0GLOIIbh796Y/9z7//BO4yAXQO9jcxeFKwiB2zYlu
+ZOVDOiFFgqqbMg==
+-----END PUBLIC KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pub-512.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pub-512.der
new file mode 100644
index 0000000000..5d60a6576a
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pub-512.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pub-512.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pub-512.pem
new file mode 100644
index 0000000000..df5f99982e
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pub-512.pem
@@ -0,0 +1,8 @@
+-----BEGIN PUBLIC KEY-----
+MIHxMIGoBgcqhkjOOAQBMIGcAkEA2tY9+lNVCnDx//ciofnvm/OPWi7oMQ6XFFfX
+rpjltIG+9eRQv0j4SqcwHpsqcaC4vjsbHFTDR0p8UyUAbrXzLwIVAOKRP6SgXHve
+EJ//aztaVltEWqBBAkAj1tdgG3FQBxG5UJQGl53XsOOBJ9xz21RrrrlkqCO9G9Cl
+NjmQ1XzrkBHije1MPb6iOLH1aPYiY6svkxaDMb88A0QAAkEAzobcabWo6sag70pa
+K/ihZlSbd4EC5Hl1XjtC5sKFBkjLK3A79f9TobAwDiHzSxdiLNT0xKd+iOKoWZnA
+j+TJ2A==
+-----END PUBLIC KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pub-576.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pub-576.der
new file mode 100644
index 0000000000..8c67395210
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pub-576.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pub-576.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pub-576.pem
new file mode 100644
index 0000000000..3a594bfecb
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pub-576.pem
@@ -0,0 +1,8 @@
+-----BEGIN PUBLIC KEY-----
+MIIBCDCBuAYHKoZIzjgEATCBrAJJANeKU0IdVgDc/dVL6vrEjgZW8lMLrUyjYDhu
+65sl8LaOmamwvozxISFjYaeIMPCloHnn2jijsjQpjnlj5rVRT1MYWt2i56jV+wIV
+ANvg9uDO7mNdcuOWuT+xveysakC9Akg2q1Vi56KzKVR4T2KIS4yTH3bz2wwiWd80
+p+SylyOkM/fSIrxJIRYGugR1WY7lgWAI8E0mJDXKmajpGSvysDHnjdlSpSVSUNID
+SwACSD9wBxobS/ySpKs+ks11XCPyZiMsf+LjUtT7nK5RBTG0PDEw+82MchouPc4Y
+UPGR+Qf64GB7AxBYQpt/YhLXtFVCocZUt0HJBw==
+-----END PUBLIC KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pub-960.der b/tests/auto/network/ssl/qsslkey/keys/dsa-pub-960.der
new file mode 100644
index 0000000000..58c80e805e
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pub-960.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/dsa-pub-960.pem b/tests/auto/network/ssl/qsslkey/keys/dsa-pub-960.pem
new file mode 100644
index 0000000000..bcdc9e343e
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/dsa-pub-960.pem
@@ -0,0 +1,11 @@
+-----BEGIN PUBLIC KEY-----
+MIIBmjCCARkGByqGSM44BAEwggEMAnkAwOYxuM+5A4k53ntkHJry0gKxJtEaj7JK
+1GbSu5uoCeMrOAw5lzwJZP7/Z11Vgq5ALMbQMRh4bIHEZRI/ZntNCtUn/gaYct4c
+kiIgFPwkCH7IeYNaE06wpluxS2xyTAES6H/W+z74v49fxAa8cITpj6wVNHrEKzoR
+AhUA7+CKC3uwSnczMiFwUYuJPo+Vs00CeH4YWTZwl5ysxunDd1PmKVM9mRabyfIL
+/V8nBWTh0R1jvKMCcJdK7V47WbpEsz86VVcxPzgcpqoD3nDT12Dyz0uaWspHlE4f
+oxdig7B6jAVx38+sl3tTewZE3tzDNURbz89k4NgljQBvRuGmNBh4w5tB/rW3eJER
+tQN7AAJ4Hope30Oi4ftxxZeR4kzRR/55cLE9uczAyxHpp7cXYb9g2VquqQojcKm7
+BwojUe+reKK3Oc8+ZkmuqUbLAj56zlrGqyRtX/s1jpVzBodVHcVx1KmSzEK4bnM/
+cYSpVLtvdY+P3yMEYxvRUHgK0roKnGMLbzf9i7Lx
+-----END PUBLIC KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/genkeys.sh b/tests/auto/network/ssl/qsslkey/keys/genkeys.sh
new file mode 100755
index 0000000000..559ef5cf5d
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/genkeys.sh
@@ -0,0 +1,82 @@
+#!/bin/sh
+#############################################################################
+##
+## Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+## All rights reserved.
+## Contact: Nokia Corporation (qt-info@nokia.com)
+##
+## This file is the build configuration utility of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## GNU Lesser General Public License Usage
+## This file may be used under the terms of the GNU Lesser General Public
+## License version 2.1 as published by the Free Software Foundation and
+## appearing in the file LICENSE.LGPL included in the packaging of this
+## file. Please review the following information to ensure the GNU Lesser
+## General Public License version 2.1 requirements will be met:
+## http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+##
+## In addition, as a special exception, Nokia gives you certain additional
+## rights. These rights are described in the Nokia Qt LGPL Exception
+## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU General
+## Public License version 3.0 as published by the Free Software Foundation
+## and appearing in the file LICENSE.GPL included in the packaging of this
+## file. Please review the following information to ensure the GNU General
+## Public License version 3.0 requirements will be met:
+## http://www.gnu.org/copyleft/gpl.html.
+##
+## Other Usage
+## Alternatively, this file may be used in accordance with the terms and
+## conditions contained in a signed written agreement between you and Nokia.
+##
+##
+##
+##
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+# This script generates cryptographic keys of different types.
+
+#--- RSA ---------------------------------------------------------------------------
+# Note: RSA doesn't require the key size to be divisible by any particular number
+for size in 40 511 512 999 1023 1024 2048
+do
+ echo -e "\ngenerating RSA private key to PEM file ..."
+ openssl genrsa -out rsa-pri-$size.pem $size
+
+ echo -e "\ngenerating RSA private key to DER file ..."
+ openssl rsa -in rsa-pri-$size.pem -out rsa-pri-$size.der -outform DER
+
+ echo -e "\ngenerating RSA public key to PEM file ..."
+ openssl rsa -in rsa-pri-$size.pem -pubout -out rsa-pub-$size.pem
+
+ echo -e "\ngenerating RSA public key to DER file ..."
+ openssl rsa -in rsa-pri-$size.pem -pubout -out rsa-pub-$size.der -outform DER
+done
+
+#--- DSA ----------------------------------------------------------------------------
+# Note: DSA requires the key size to be in interval [512, 1024] and be divisible by 64
+for size in 512 576 960 1024
+do
+ echo -e "\ngenerating DSA parameters to PEM file ..."
+ openssl dsaparam -out dsapar-$size.pem $size
+
+ echo -e "\ngenerating DSA private key to PEM file ..."
+ openssl gendsa dsapar-$size.pem -out dsa-pri-$size.pem
+
+ /bin/rm dsapar-$size.pem
+
+ echo -e "\ngenerating DSA private key to DER file ..."
+ openssl dsa -in dsa-pri-$size.pem -out dsa-pri-$size.der -outform DER
+
+ echo -e "\ngenerating DSA public key to PEM file ..."
+ openssl dsa -in dsa-pri-$size.pem -pubout -out dsa-pub-$size.pem
+
+ echo -e "\ngenerating DSA public key to DER file ..."
+ openssl dsa -in dsa-pri-$size.pem -pubout -out dsa-pub-$size.der -outform DER
+done
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-1023.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-1023.der
new file mode 100644
index 0000000000..d23dde8058
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-1023.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-1023.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-1023.pem
new file mode 100644
index 0000000000..bd1c119217
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-1023.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICWQIBAAKBgF0LbcbxSbBWA+7N9kaZ1OHRChPCN74g69SuV29p+CkRcgReeZHB
+LkEcTERBUn5hw4AlgbmbVEFplLs/bbqS7hOK/Pkz9TCM9wG2j8T2mcPIi8NU8RMc
+oNyVINlVduKxSID491sRZuQXLX+CM7klIA7rpcdsfefpuhPu0yTCJ1wJAgMBAAEC
+gYAVxvYDqTfREODMxOIOdjTQQaf1JfD8DCKGXePTDN9rZUzlXuNfTPKxhJkJJKzV
+LbafSKgLNCLNSJPqG5doIrmcCU4r4qVhjyQtTQ8orFaIKjWgrvIUXh8DIioKOD3o
+ikiJvg0A7oL4+F/jHqpeUzzlNOyGRRsNP95DJUor1UuT3QJBAMD7qNUXYxDLtjs9
+VFRRN7KkUvBz4FXD+XwgE1ZrYQEy7IN/ZaHeFGb/59WbQc5LEwDY5N+GFlwWm0pQ
+6iZdj4cCQHttdWhXcutPDZOUs6JHq8Q6q9j8USGyhmJ3nOKnbGOLhimvlceW+P0n
+AjGnFhicIdr7sht1HgacsfHxT+WD++8CQGQDyRsu9LOmr/oBrevI79HQof9mPpSU
+bX8r7Hm0SuDhMHxyEQ0T2IUNCWzF+xPcCqw8vFkv1/S/7plUWBWsFY8CQGnrFMXl
+xYiI3m23PjAUsSJD9xTN8hGo0gnN+6PFaQ5DvW4ob7BHroQP5aIWcK/NzH/PXpiR
+eKLT9SBapOWgzaECQFp8lWNJpW4dK2w0XafRB3fwQ/OOvv4EWTOCsbHEmNg/RgIG
+HKNAZekwBn9lfnYRaKC7z9VtTEy6mmMnaLE6Srw=
+-----END RSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-1024.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-1024.der
new file mode 100644
index 0000000000..0ea20598f0
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-1024.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-1024.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-1024.pem
new file mode 100644
index 0000000000..f2fc5b0064
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-1024.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQDN8qIMJKzoi0rUWBYx7ggiUATFLITKbHQ+sdeb3JKwzHv4pLY1
+YNsQWd+RD1tLUN5qJNrj4b8GWyJ4pipxr9Dq0Ak5b0Qvhuell5a8JVrUSRvsfUvc
+VlNY6yv7JZKetCYmCEF/IkRc4RegS8bEOU4lddN3RotDsu6eZ7/sgyPd0wIDAQAB
+AoGAIXeecc678oZAQMWXxcFivQC35brYUXTSZyXLXd64T9bLBprtqTr2HnAcbpxK
+P7ECk8ktcP7MZiIFNgn6t8LUdik34iMdkzqAG4w4g/qET1ANd+cvGs6Ct5b+82HY
+7s4sGXsOyU9BKltHrjSSEn3EIhC58GZQpJADNoiBb63f5kECQQD50SNoeb3LcFs/
+peZNcbpm7yR3BEkDYm94iENmP/Su4Y38OJ/cArmEODj/pg6UAgtq6r5ARjfQUKkz
+G+WD421jAkEA0wuJMMRtNh8ellc7BEbmVpgWCOZFjDXAyH0atv+THDnhq5bs4PNh
+ldc+PDVO6b3BXxanzrfH19qE9P1xTscw0QJABPKhcuZGXgsho4cToqEIAhXmcP0C
+vTBr6MU6IIJPxE7vUvmEIQVkyzuZ1WZij4fi1gFEN12sqVGPqFV7HDua5QJADfTf
+V7hFuKSKM0sFfhzqMqPQITqJMuKDIz8SuzNfmShCwkQy2hV+SJh5ZyXnWBHSbeVj
+p4oDz0SGMmVoTtthYQJBAOJeHHuQ7M/rZjHWRiVFnyAh/WfBdD1d/4JgfjsHJUEp
+yCfMpEw5Nb1vBdlhKIn1tTBUMX5WCeQaZWIi1g9OAnU=
+-----END RSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-2048.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-2048.der
new file mode 100644
index 0000000000..194da2adf2
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-2048.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-2048.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-2048.pem
new file mode 100644
index 0000000000..125d281792
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-2048.pem
@@ -0,0 +1,27 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIEogIBAAKCAQEAuwQ1KqA3hewLXsG9fHD7UI3fQu5ylQiDeRWEwsFovmiDfDNo
+7P/VuByvQmVR30p3GzNnZdMsj8jVlLD/Wny1nU/O2T00KQ95SJhiEGGCVWirRf/7
+F1KrFGP7HuiQ76FQwqtRxBDQw3QOm2PXp20EpyzGdYpY13EkY6n0FLumWoJxL+2g
+TW0ECyLulxXFK9wXCNWnY+ji5V8VwDfkXk7WXYzMawnFnKNiSJ99jkfJ28lo+Ba8
+LAfvHM6ygeudWndri6pGkA/R0Z3knca6yz5YJCMph5AKgj9beOaLsIWEbdbmZA7f
+zuu8QhBK6cjvjUbS6iPVDEfBnI6TOpGPJxvWNwIDAQABAoIBAE5bZfdVJ85Z5y2t
+mToBkJrgxpGhnKqq5YMfK//5z2wwGB863xSl4KMCicAU+afH6H2iHQmB4GLiL/Lb
+8jG0nNerr6w/w5IMpLFw/22DnXsxnsl2hnrwLTQe7AG4SbnNaiwWYez3arDp+JDM
+1XeV6uQsk35+F9k0051agSUKtpmm5Be9bu6lW8a55gJsAvUIrj0eLxXN7nxhI6tL
+W1fwylJUX0ACka5SMsFOue7UPxPEGpM2OHI64T3QWpgoaXwyfNyn22u4PHOiWOtt
+io/r5Ta61mf8FiSV8X33/nm/yjUpW2EKJuIxA8IWcrADTyQrO5AKq0MFJjQVy8I+
+jrx0pzkCgYEA6LJp/slfTiz6Y9b5GVFY48QL+msorvjuyPdGwEkkCGAjo8E24Lac
+91T2Bx3XKxTrqyu8FDwa0RQzXresM0Tqvi3WT/oIauuiZL2U3ef32QQ42tvOWmGM
+09hES8Ymx78xFUzh20AdzAfLGaxvQ4Z19yt/aGmZH1/Giyc+TO8rBusCgYEAzb6y
+FMQSYvnvQTLI2qUt1h/kjU01JdCkGRgfMyyAW/pYq56vPJBKvsnrH0rDmICY3Cam
+Ma4hf7HekfqbIyYw+cklxZHYmVPf16T9Tyopwwltf8k9mULwnsSY7Cti2VBGcAGs
+DbgYz9HoJERe2qfgWKuTGXMHTXh5+x28bncecuUCgYAZGITN8bHRoJAwjFK5JEjN
+56rTCxOMK1S1X9XFjx3PuW6ejov4mDk9g3A1PEakYtE32LOkCwdpXSBdKrnrnZcj
+g5YFchXOUjNlYfzYIdhdE1N+Zw5OOQ8TGdPjyC8Og9QrU+tX1gZgpsaEslAdnDbE
+vXA0No9JDu8+urDBY1nkmQKBgCxwErCPhNUh3H49hMpMwPCtpMSsN116iebtodeA
+thynnr06oei31Z0NqZ3xnPt0Uw/BvUWfsZaOCV+IPDfESPG6c1EP5jN/vSordZbC
+qZB5mc/u3EIdBjGUjt77o/cB8qTAh7PS3nEMilJC/iXF+pvMOxJVGO+vpNELJCbL
+zaTNAoGAQ7qhJUUWENzWbuh1g/bYy/980/nhE24iWGwQgFeQOrUnghBLQvUUp7a0
+kwNqZmlxl97HCxusM2T/lZoPvMBWhzfszzbaZchiOWIkbUXiHTrVsRnBHysHTpD+
+bsHGs9ILGSEYymWOErGII5wZ5DJOVUmtzCrgRvyZfxbH/lOZSZc=
+-----END RSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-40.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-40.der
new file mode 100644
index 0000000000..227cbbba00
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-40.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-40.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-40.pem
new file mode 100644
index 0000000000..e480b11029
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-40.pem
@@ -0,0 +1,4 @@
+-----BEGIN RSA PRIVATE KEY-----
+MC8CAQACBgC+dq4BGQIDAQABAgVOUamohQIDDtUPAgMM11cCAnzbAgMA350CAwIz
+jw==
+-----END RSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-511.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-511.der
new file mode 100644
index 0000000000..43da25456e
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-511.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-511.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-511.pem
new file mode 100644
index 0000000000..70872d9814
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-511.pem
@@ -0,0 +1,9 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIBOAIBAAJAVFNCgrdkp5mE62MBco89Ip/tbJdHq09d8Q72Kw0SERi8zoXewZR7
+NwlcAns+boTWCzgRfIs051qZGzao9o+jaQIDAQABAkA111ePSPOew7oH5ZZGBElf
+s0eQX2NmcW2k/g2V3Wmcui+ejz9edzsooCXYBiLtfAIHNq0MwOLkl6kmxfoeGgAV
+AiEAxnr8EPGStCvtIf4IFKHZdbl/+FanTVec0WqLPW+U2vMCIGzDPosDi74f30vi
+78PfdSgy+pp4Sp/0pSttHBrQfyczAiEAkRTa5gO/ScYGG1/WRkacb2o9+ahVuLo/
+HfC0gR7r/zMCIBi+53j7iozsdYKvlHvNWLuXtbr1iY0RPY8+2Pkk3PlPAiB3CDCM
+Pu1PssfpwYB0Lr68Mnx1oiZPLZje5HAVzptD6A==
+-----END RSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512.der
new file mode 100644
index 0000000000..156a1d1439
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512.pem
new file mode 100644
index 0000000000..dda274f50c
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-512.pem
@@ -0,0 +1,9 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIBPAIBAAJBAOyVSr5qVl/cuVAbjSs1cLFi17mJXg8X9vQC9xb4BjHUY9i60vIV
+zAaE9knwaNkRwPfxgzp244WGFzXRO7UwHKECAwEAAQJBAOCAMvNKmThSjg90dZuh
+FJVfxHIt5nHQPeoDvlGvfsFchWLI42451QTKbXFlSBLb2F4kCVrzLZN5zrGfcagy
+pgECIQD4pPthJoUmQVCLqMJKgtFPzfwSetxYe8+BFeBKupSz8QIhAPOU998ZEmzB
+YPajTzmUK9SIxk88m93O5GSqC+HS4eOxAiBHbM0xaSlSheynUcEOOmn6LMe+X0Cw
+wlAnWqtljBdvYQIhAJiIoPBEcxVHw8CvY91avFfLjuPvwGuWM9AV7Hrt5CcBAiEA
+ykI2wY34X9/1rodR/6CXUW5cJq7TCHt8bAsowkXH7bU=
+-----END RSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-999.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-999.der
new file mode 100644
index 0000000000..3b3f8ca6d5
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-999.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pri-999.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-999.pem
new file mode 100644
index 0000000000..6ed72bf1f9
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pri-999.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICSwIBAAJ9ZTk4kN4YU/14BJi/Fsa0cgMnN7hzZIGD0Tw5kzTBh2SKPkd5TkaM
+saWAsI+ZBICDTxEAUJ4y7KW/QchROTjRI04HKBXa30rk51WQ98W9/AEN4+roWeA9
+YQ3V1nIu1lYA+Ypb4/kBW1VI9yeOTxh4QD1zyrBP3CQ1wQrhth8CAwEAAQJ9El4T
+uZXTbEouIQdmhUeBLr8Lurypk688sBbxi5ijFWJVA4AMrvt2RDX36BHmfj6jlRFM
+sVRDgVWCIvmqY2u8I0YuHoLRc7Xsg6ICQljxz0H5frs2q4suc2AHEbxBstlUWHSQ
+fYDyNq/b1xf5+LOCeU6VP9z3ZwtHydACgYECPwzrRsj4dMIs2/i6Vs0Epa8gf4Oc
+kw+e1sjigFkvpA/iDJl39wG+lJQkYEfJEY2cfCCIBreof9sKtq6SP3a3kQI/B9XQ
+nsjhw71h6lV/dOUFRmSYV7fJDIIqZEA+NvO24kRjbSagKXNKFWRgq/SRzbT9Z4vC
+WPhhCYbi6zeU/ZqvAj8Bi/FPgh9IV+KF5pkZtmK3kqZxdT9N8XA5YJSJGOEFXcSw
+YuJZfR2AltJIBdRqJb/ejSpwtmWILcItKCkc52ECPwM4rKJsEy6IMbbH2jR0aNvN
+Rjlibb2/0rAPHcU4JKwY1AwvglAof4AWGgz46+14iWtGMeykijkBhVCSNKakLwI/
+Bjzrf1iLEl3ylN47Cukse7sKSXI58tUaIJprjihMO/64dVK1ZdkXVGLMft9Eq+7l
+wTVe2ajpMWFm9wAD8114
+-----END RSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pub-1023.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-1023.der
new file mode 100644
index 0000000000..4b16fdddd0
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-1023.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pub-1023.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-1023.pem
new file mode 100644
index 0000000000..174a135514
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-1023.pem
@@ -0,0 +1,6 @@
+-----BEGIN PUBLIC KEY-----
+MIGeMA0GCSqGSIb3DQEBAQUAA4GMADCBiAKBgF0LbcbxSbBWA+7N9kaZ1OHRChPC
+N74g69SuV29p+CkRcgReeZHBLkEcTERBUn5hw4AlgbmbVEFplLs/bbqS7hOK/Pkz
+9TCM9wG2j8T2mcPIi8NU8RMcoNyVINlVduKxSID491sRZuQXLX+CM7klIA7rpcds
+fefpuhPu0yTCJ1wJAgMBAAE=
+-----END PUBLIC KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pub-1024.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-1024.der
new file mode 100644
index 0000000000..96495920d0
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-1024.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pub-1024.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-1024.pem
new file mode 100644
index 0000000000..d5c8da9144
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-1024.pem
@@ -0,0 +1,6 @@
+-----BEGIN PUBLIC KEY-----
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDN8qIMJKzoi0rUWBYx7ggiUATF
+LITKbHQ+sdeb3JKwzHv4pLY1YNsQWd+RD1tLUN5qJNrj4b8GWyJ4pipxr9Dq0Ak5
+b0Qvhuell5a8JVrUSRvsfUvcVlNY6yv7JZKetCYmCEF/IkRc4RegS8bEOU4lddN3
+RotDsu6eZ7/sgyPd0wIDAQAB
+-----END PUBLIC KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pub-2048.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-2048.der
new file mode 100644
index 0000000000..560487b67e
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-2048.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pub-2048.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-2048.pem
new file mode 100644
index 0000000000..95daf33896
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-2048.pem
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuwQ1KqA3hewLXsG9fHD7
+UI3fQu5ylQiDeRWEwsFovmiDfDNo7P/VuByvQmVR30p3GzNnZdMsj8jVlLD/Wny1
+nU/O2T00KQ95SJhiEGGCVWirRf/7F1KrFGP7HuiQ76FQwqtRxBDQw3QOm2PXp20E
+pyzGdYpY13EkY6n0FLumWoJxL+2gTW0ECyLulxXFK9wXCNWnY+ji5V8VwDfkXk7W
+XYzMawnFnKNiSJ99jkfJ28lo+Ba8LAfvHM6ygeudWndri6pGkA/R0Z3knca6yz5Y
+JCMph5AKgj9beOaLsIWEbdbmZA7fzuu8QhBK6cjvjUbS6iPVDEfBnI6TOpGPJxvW
+NwIDAQAB
+-----END PUBLIC KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pub-40.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-40.der
new file mode 100644
index 0000000000..3d789a7e11
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-40.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pub-40.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-40.pem
new file mode 100644
index 0000000000..f053580d90
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-40.pem
@@ -0,0 +1,3 @@
+-----BEGIN PUBLIC KEY-----
+MCEwDQYJKoZIhvcNAQEBBQADEAAwDQIGAL52rgEZAgMBAAE=
+-----END PUBLIC KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pub-511.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-511.der
new file mode 100644
index 0000000000..2da3341554
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-511.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pub-511.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-511.pem
new file mode 100644
index 0000000000..a5135f0e4c
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-511.pem
@@ -0,0 +1,4 @@
+-----BEGIN PUBLIC KEY-----
+MFswDQYJKoZIhvcNAQEBBQADSgAwRwJAVFNCgrdkp5mE62MBco89Ip/tbJdHq09d
+8Q72Kw0SERi8zoXewZR7NwlcAns+boTWCzgRfIs051qZGzao9o+jaQIDAQAB
+-----END PUBLIC KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pub-512.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-512.der
new file mode 100644
index 0000000000..372ba8f8b5
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-512.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pub-512.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-512.pem
new file mode 100644
index 0000000000..d3a5e5882f
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-512.pem
@@ -0,0 +1,4 @@
+-----BEGIN PUBLIC KEY-----
+MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAOyVSr5qVl/cuVAbjSs1cLFi17mJXg8X
+9vQC9xb4BjHUY9i60vIVzAaE9knwaNkRwPfxgzp244WGFzXRO7UwHKECAwEAAQ==
+-----END PUBLIC KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pub-999.der b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-999.der
new file mode 100644
index 0000000000..1d28000501
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-999.der
Binary files differ
diff --git a/tests/auto/network/ssl/qsslkey/keys/rsa-pub-999.pem b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-999.pem
new file mode 100644
index 0000000000..00ba47915a
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/keys/rsa-pub-999.pem
@@ -0,0 +1,6 @@
+-----BEGIN PUBLIC KEY-----
+MIGaMA0GCSqGSIb3DQEBAQUAA4GIADCBhAJ9ZTk4kN4YU/14BJi/Fsa0cgMnN7hz
+ZIGD0Tw5kzTBh2SKPkd5TkaMsaWAsI+ZBICDTxEAUJ4y7KW/QchROTjRI04HKBXa
+30rk51WQ98W9/AEN4+roWeA9YQ3V1nIu1lYA+Ypb4/kBW1VI9yeOTxh4QD1zyrBP
+3CQ1wQrhth8CAwEAAQ==
+-----END PUBLIC KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/qsslkey.pro b/tests/auto/network/ssl/qsslkey/qsslkey.pro
new file mode 100644
index 0000000000..5a90b76219
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/qsslkey.pro
@@ -0,0 +1,32 @@
+load(qttest_p4)
+
+SOURCES += tst_qsslkey.cpp
+!wince*:win32:LIBS += -lws2_32
+QT = core network
+
+TARGET = tst_qsslkey
+
+win32 {
+ CONFIG(debug, debug|release) {
+ DESTDIR = debug
+} else {
+ DESTDIR = release
+ }
+}
+
+wince*|symbian: {
+ keyFiles.files = keys
+ keyFiles.path = .
+
+ passphraseFiles.files = rsa-without-passphrase.pem rsa-with-passphrase.pem
+ passphraseFiles.path = .
+
+ DEPLOYMENT += keyFiles passphraseFiles
+}
+
+wince*: {
+ DEFINES += SRCDIR=\\\".\\\"
+} else:!symbian {
+ DEFINES+= SRCDIR=\\\"$$PWD\\\"
+ TARGET.CAPABILITY = NetworkServices
+}
diff --git a/tests/auto/network/ssl/qsslkey/rsa-with-passphrase.pem b/tests/auto/network/ssl/qsslkey/rsa-with-passphrase.pem
new file mode 100644
index 0000000000..cb29becc31
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/rsa-with-passphrase.pem
@@ -0,0 +1,18 @@
+-----BEGIN RSA PRIVATE KEY-----
+Proc-Type: 4,ENCRYPTED
+DEK-Info: DES-CBC,36BD1242254C5E1E
+
+sqt8qlQfkjJiz0djd0WYjhN/IGxA/nU/wVKuf5RWDAghDBrABzJ3dU4Jh1WIsS4+
+f22TBr6fwgjpPxGkt361Z9oxon/QeyBZLFtyUxnFSqZcVMMR3vndtMyYJbVKjRm1
+lvF3BjFWNh6+SZe20cut2GiUJDqhw7RbjaAN6LaCpFqwusY6vbjW6vzB8ezDvLou
+5jQAkwArGoI0KqUMwBOYukiWdBA0iERavspKGRnB3mGtgv5ziTEFzx58mn1Lv3Qs
+LYQqTYgzpFyAMP9SZaRv4m/y5O9foAXnlh0GhmDWBQ2D5flwZqrIAzoJ5BcZKU6/
+HJCh4snw3kheeE8NhrlzypEONedvu4ifUbqN5idMU7S4t40NAmQ/dF0Z4wDen/M/
+iFbt5tTWh6sXK82XzJtAfprH07odtJHK7CMeurCi5BupmnLtPbUrl6hpKItBzu+g
+7MB5AyNk548V9Y8+kKBtEG5EgYZrMYX4yqQ+Z8F1hy0UUMXu9cAnO06OTavxLtWJ
+ikmwYJNy421Hj+oZVSagCUILQyUfgx6fXWwDRqy/stlX+hpPPjVmd/A2WBm5x/Sf
+5CGfUtddZRuAZpChBXV6a/R+nMzDXhkKl4XTkN8hg3yXLY6xy3CR3RIYDlKkn85y
+VziP32V6Bc8ucGifsZLNnvj8CFXTZP+8CWun9yLSkcq+wm4cQOLswztEMA8bbPJQ
+g7Gp59BC4ofN5bMZ1R1z+l96x+YMY9btkyjE1uEyRT88dHwxnkhC5AKBx2P6sg0C
+doe5Dh8Ny5Ic24ibwyvZbAS46tSVdha7ACGnGXV4Z3iqBfN0b0UNmw==
+-----END RSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/rsa-without-passphrase.pem b/tests/auto/network/ssl/qsslkey/rsa-without-passphrase.pem
new file mode 100644
index 0000000000..f7c834b116
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/rsa-without-passphrase.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQC1mZlLC6g8/vaw8XEOQ59gwQ5WxIvcKCSx7B5SHaeN8zzbENpl
+32BtyfrCccHF7j6qwfMZ2RwM5RTlFw/eBF4SSXAgp/P5CgcugSs1dOJUfPveos/5
+h3fmnUcKeQIU4m5EGcQicmR8//WUUfdtHDp/fJ0dRXcY2tTOx89vNPEtgwIDAQAB
+AoGBAKqE2f4vqf/sYPPxInmEYclWPgKXd8R4JUy0LBxrIAQYXBJPluOFhmRQ/hdK
+/eq/NTTd/UlOJhqtmJsstoeAjlsELl2AejX2n1B9aSffQ0WzdB5gVMNotPGRKRIG
+eOq2pp2JOFkGps11LUAqDEMNUb3EV6HiBucoGEOUpdITLrRxAkEA4Ul3o44wMvIb
+muwp7/erSvDMWRZ1GjksEmBMAHL6y8avZd9UgrjHeCy8uHXrT0id4Cig8FA+nQA5
+UwTr9y5e9wJBAM5bc8xuAuCg4Si3exssFfxQIxFTmPzhkVubglO9IcLqfXLl3k5S
+CxgRb/4pBMKVRCMRXAkaZpjJqTIofjp4ptUCQQC4hySnot932zchPi9bjtGPII1A
+q1RfllSy+I1IEOW745HnL3ZZXGCF3p71uCB1YFVwNdcc/51Jm9VYWr+sRx8hAkBL
+KoTDsk7aA8AAVNVC0Iwxm/8qEIlpk8Ce3cZbOklR9pg7gf+4B6qC2dcxfT9+oWBw
+ZaJgrn0wqkQ3QQi5w7kBAkBAR2tKc2OqnljMPnXYEreRyHHjhqCsJYFAE7u16cY/
+NQGJq9jBAD5WANclrYRxKtD6yohi+Y7Vi7+SXve3pGdF
+-----END RSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp b/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp
new file mode 100644
index 0000000000..ac966ce74a
--- /dev/null
+++ b/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp
@@ -0,0 +1,447 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include <qsslkey.h>
+#include <qsslsocket.h>
+
+#include <QtNetwork/qhostaddress.h>
+#include <QtNetwork/qnetworkproxy.h>
+
+#ifdef Q_OS_SYMBIAN
+// In Symbian OS test data is located in applications private dir
+// Current path (C:\private\<UID>) contains only ascii chars
+#define SRCDIR "."
+#endif
+
+class tst_QSslKey : public QObject
+{
+ Q_OBJECT
+
+ struct KeyInfo {
+ QFileInfo fileInfo;
+ QSsl::KeyAlgorithm algorithm;
+ QSsl::KeyType type;
+ int length;
+ QSsl::EncodingFormat format;
+ KeyInfo(
+ const QFileInfo &fileInfo, QSsl::KeyAlgorithm algorithm, QSsl::KeyType type,
+ int length, QSsl::EncodingFormat format)
+ : fileInfo(fileInfo), algorithm(algorithm), type(type), length(length)
+ , format(format) {}
+ };
+
+ QList<KeyInfo> keyInfoList;
+
+ void createPlainTestRows();
+
+public:
+ tst_QSslKey();
+ virtual ~tst_QSslKey();
+
+public slots:
+ void initTestCase_data();
+ void init();
+ void cleanup();
+
+#ifndef QT_NO_OPENSSL
+
+private slots:
+ void emptyConstructor();
+ void constructor_data();
+ void constructor();
+ void copyAndAssign_data();
+ void copyAndAssign();
+ void equalsOperator();
+ void length_data();
+ void length();
+ void toPemOrDer_data();
+ void toPemOrDer();
+ void toEncryptedPemOrDer_data();
+ void toEncryptedPemOrDer();
+
+ void passphraseChecks();
+#endif
+};
+
+tst_QSslKey::tst_QSslKey()
+{
+#ifdef Q_WS_MAC
+ // applicationDirPath() points to a path inside the app bundle on Mac.
+ QDir dir(qApp->applicationDirPath() + QLatin1String("/../../../keys"));
+#else
+ QDir dir(SRCDIR + QLatin1String("/keys")); // prefer this way to avoid ifdeffery and support shadow builds?
+#endif
+ QFileInfoList fileInfoList = dir.entryInfoList(QDir::Files | QDir::Readable);
+ QRegExp rx(QLatin1String("^(rsa|dsa)-(pub|pri)-(\\d+)\\.(pem|der)$"));
+ foreach (QFileInfo fileInfo, fileInfoList) {
+ if (rx.indexIn(fileInfo.fileName()) >= 0)
+ keyInfoList << KeyInfo(
+ fileInfo,
+ rx.cap(1) == QLatin1String("rsa") ? QSsl::Rsa : QSsl::Dsa,
+ rx.cap(2) == QLatin1String("pub") ? QSsl::PublicKey : QSsl::PrivateKey,
+ rx.cap(3).toInt(),
+ rx.cap(4) == QLatin1String("pem") ? QSsl::Pem : QSsl::Der);
+ }
+}
+
+tst_QSslKey::~tst_QSslKey()
+{
+}
+
+void tst_QSslKey::initTestCase_data()
+{
+}
+
+void tst_QSslKey::init()
+{
+}
+
+void tst_QSslKey::cleanup()
+{
+}
+
+static QByteArray readFile(const QString &absFilePath)
+{
+ QFile file(absFilePath);
+ if (!file.open(QIODevice::ReadOnly)) {
+ QWARN("failed to open file");
+ return QByteArray();
+ }
+ return file.readAll();
+}
+
+#ifndef QT_NO_OPENSSL
+
+void tst_QSslKey::emptyConstructor()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QSslKey key;
+ QVERIFY(key.isNull());
+ QVERIFY(key.length() < 0);
+
+ QSslKey key2;
+ QCOMPARE(key, key2);
+}
+
+Q_DECLARE_METATYPE(QSsl::KeyAlgorithm)
+Q_DECLARE_METATYPE(QSsl::KeyType)
+Q_DECLARE_METATYPE(QSsl::EncodingFormat)
+
+void tst_QSslKey::createPlainTestRows()
+{
+ QTest::addColumn<QString>("absFilePath");
+ QTest::addColumn<QSsl::KeyAlgorithm>("algorithm");
+ QTest::addColumn<QSsl::KeyType>("type");
+ QTest::addColumn<int>("length");
+ QTest::addColumn<QSsl::EncodingFormat>("format");
+ foreach (KeyInfo keyInfo, keyInfoList) {
+ QTest::newRow(keyInfo.fileInfo.fileName().toLatin1())
+ << keyInfo.fileInfo.absoluteFilePath() << keyInfo.algorithm << keyInfo.type
+ << keyInfo.length << keyInfo.format;
+ }
+}
+
+void tst_QSslKey::constructor_data()
+{
+ createPlainTestRows();
+}
+
+void tst_QSslKey::constructor()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QFETCH(QString, absFilePath);
+ QFETCH(QSsl::KeyAlgorithm, algorithm);
+ QFETCH(QSsl::KeyType, type);
+ QFETCH(QSsl::EncodingFormat, format);
+
+ QByteArray encoded = readFile(absFilePath);
+ QSslKey key(encoded, algorithm, format, type);
+ QVERIFY(!key.isNull());
+}
+
+void tst_QSslKey::copyAndAssign_data()
+{
+ createPlainTestRows();
+}
+
+void tst_QSslKey::copyAndAssign()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QFETCH(QString, absFilePath);
+ QFETCH(QSsl::KeyAlgorithm, algorithm);
+ QFETCH(QSsl::KeyType, type);
+ QFETCH(QSsl::EncodingFormat, format);
+
+ QByteArray encoded = readFile(absFilePath);
+ QSslKey key(encoded, algorithm, format, type);
+
+ QSslKey copied(key);
+ QCOMPARE(key, copied);
+ QCOMPARE(key.algorithm(), copied.algorithm());
+ QCOMPARE(key.type(), copied.type());
+ QCOMPARE(key.length(), copied.length());
+ QCOMPARE(key.toPem(), copied.toPem());
+ QCOMPARE(key.toDer(), copied.toDer());
+
+ QSslKey assigned = key;
+ QCOMPARE(key, assigned);
+ QCOMPARE(key.algorithm(), assigned.algorithm());
+ QCOMPARE(key.type(), assigned.type());
+ QCOMPARE(key.length(), assigned.length());
+ QCOMPARE(key.toPem(), assigned.toPem());
+ QCOMPARE(key.toDer(), assigned.toDer());
+}
+
+void tst_QSslKey::equalsOperator()
+{
+ // ### unimplemented
+}
+
+void tst_QSslKey::length_data()
+{
+ createPlainTestRows();
+}
+
+void tst_QSslKey::length()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QFETCH(QString, absFilePath);
+ QFETCH(QSsl::KeyAlgorithm, algorithm);
+ QFETCH(QSsl::KeyType, type);
+ QFETCH(int, length);
+ QFETCH(QSsl::EncodingFormat, format);
+
+ QByteArray encoded = readFile(absFilePath);
+ QSslKey key(encoded, algorithm, format, type);
+ QVERIFY(!key.isNull());
+ QCOMPARE(key.length(), length);
+}
+
+void tst_QSslKey::toPemOrDer_data()
+{
+ createPlainTestRows();
+}
+
+void tst_QSslKey::toPemOrDer()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QFETCH(QString, absFilePath);
+ QFETCH(QSsl::KeyAlgorithm, algorithm);
+ QFETCH(QSsl::KeyType, type);
+ QFETCH(QSsl::EncodingFormat, format);
+
+ QByteArray encoded = readFile(absFilePath);
+ QSslKey key(encoded, algorithm, format, type);
+ QVERIFY(!key.isNull());
+ if (format == QSsl::Pem)
+ encoded.replace('\r', "");
+ QCOMPARE(format == QSsl::Pem ? key.toPem() : key.toDer(), encoded);
+}
+
+void tst_QSslKey::toEncryptedPemOrDer_data()
+{
+ QTest::addColumn<QString>("absFilePath");
+ QTest::addColumn<QSsl::KeyAlgorithm>("algorithm");
+ QTest::addColumn<QSsl::KeyType>("type");
+ QTest::addColumn<QSsl::EncodingFormat>("format");
+ QTest::addColumn<QString>("password");
+
+ QStringList passwords;
+ passwords << " " << "foobar" << "foo bar"
+ << "aAzZ`1234567890-=~!@#$%^&*()_+[]{}\\|;:'\",.<>/?"; // ### add more (?)
+ foreach (KeyInfo keyInfo, keyInfoList) {
+ foreach (QString password, passwords) {
+ QString testName = QString("%1-%2-%3-%4").arg(keyInfo.fileInfo.fileName())
+ .arg(keyInfo.algorithm == QSsl::Rsa ? "RSA" : "DSA")
+ .arg(keyInfo.type == QSsl::PrivateKey ? "PrivateKey" : "PublicKey")
+ .arg(keyInfo.format == QSsl::Pem ? "PEM" : "DER");
+ QTest::newRow(testName.toLatin1())
+ << keyInfo.fileInfo.absoluteFilePath() << keyInfo.algorithm << keyInfo.type
+ << keyInfo.format << password;
+ }
+ }
+}
+
+void tst_QSslKey::toEncryptedPemOrDer()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QFETCH(QString, absFilePath);
+ QFETCH(QSsl::KeyAlgorithm, algorithm);
+ QFETCH(QSsl::KeyType, type);
+ QFETCH(QSsl::EncodingFormat, format);
+ QFETCH(QString, password);
+
+ QByteArray plain = readFile(absFilePath);
+ QSslKey key(plain, algorithm, format, type);
+ QVERIFY(!key.isNull());
+
+ QByteArray pwBytes(password.toLatin1());
+
+ if (type == QSsl::PrivateKey) {
+ QByteArray encryptedPem = key.toPem(pwBytes);
+ QVERIFY(!encryptedPem.isEmpty());
+ QSslKey keyPem(encryptedPem, algorithm, QSsl::Pem, type, pwBytes);
+ QVERIFY(!keyPem.isNull());
+ QCOMPARE(keyPem, key);
+ QCOMPARE(keyPem.toPem(), key.toPem());
+ } else {
+ // verify that public keys are never encrypted by toPem()
+ QByteArray encryptedPem = key.toPem(pwBytes);
+ QVERIFY(!encryptedPem.isEmpty());
+ QByteArray plainPem = key.toPem();
+ QVERIFY(!plainPem.isEmpty());
+ QCOMPARE(encryptedPem, plainPem);
+ }
+
+ if (type == QSsl::PrivateKey) {
+ QByteArray encryptedDer = key.toDer(pwBytes);
+ // ### at this point, encryptedDer is invalid, hence the below QEXPECT_FAILs
+ QVERIFY(!encryptedDer.isEmpty());
+ QSslKey keyDer(encryptedDer, algorithm, QSsl::Der, type, pwBytes);
+ if (type == QSsl::PrivateKey)
+ QEXPECT_FAIL(
+ QTest::currentDataTag(), "We're not able to decrypt these yet...", Continue);
+ QVERIFY(!keyDer.isNull());
+ if (type == QSsl::PrivateKey)
+ QEXPECT_FAIL(
+ QTest::currentDataTag(), "We're not able to decrypt these yet...", Continue);
+ QCOMPARE(keyDer.toPem(), key.toPem());
+ } else {
+ // verify that public keys are never encrypted by toDer()
+ QByteArray encryptedDer = key.toDer(pwBytes);
+ QVERIFY(!encryptedDer.isEmpty());
+ QByteArray plainDer = key.toDer();
+ QVERIFY(!plainDer.isEmpty());
+ QCOMPARE(encryptedDer, plainDer);
+ }
+
+ // ### add a test to verify that public keys are _decrypted_ correctly (by the ctor)
+}
+
+void tst_QSslKey::passphraseChecks()
+{
+ {
+ QString fileName(SRCDIR "/rsa-with-passphrase.pem");
+ QFile keyFile(fileName);
+ QVERIFY(keyFile.exists());
+ {
+ if (!keyFile.isOpen())
+ keyFile.open(QIODevice::ReadOnly);
+ else
+ keyFile.reset();
+ QSslKey key(&keyFile,QSsl::Rsa,QSsl::Pem, QSsl::PrivateKey);
+ QVERIFY(key.isNull()); // null passphrase => should not be able to decode key
+ }
+ {
+ if (!keyFile.isOpen())
+ keyFile.open(QIODevice::ReadOnly);
+ else
+ keyFile.reset();
+ QSslKey key(&keyFile,QSsl::Rsa,QSsl::Pem, QSsl::PrivateKey, "");
+ QVERIFY(key.isNull()); // empty passphrase => should not be able to decode key
+ }
+ {
+ if (!keyFile.isOpen())
+ keyFile.open(QIODevice::ReadOnly);
+ else
+ keyFile.reset();
+ QSslKey key(&keyFile,QSsl::Rsa,QSsl::Pem, QSsl::PrivateKey, "WRONG!");
+ QVERIFY(key.isNull()); // wrong passphrase => should not be able to decode key
+ }
+ {
+ if (!keyFile.isOpen())
+ keyFile.open(QIODevice::ReadOnly);
+ else
+ keyFile.reset();
+ QSslKey key(&keyFile,QSsl::Rsa,QSsl::Pem, QSsl::PrivateKey, "123");
+ QVERIFY(!key.isNull()); // correct passphrase
+ }
+ }
+
+ {
+ // be sure and check a key without passphrase too
+ QString fileName(SRCDIR "/rsa-without-passphrase.pem");
+ QFile keyFile(fileName);
+ {
+ if (!keyFile.isOpen())
+ keyFile.open(QIODevice::ReadOnly);
+ else
+ keyFile.reset();
+ QSslKey key(&keyFile,QSsl::Rsa,QSsl::Pem, QSsl::PrivateKey);
+ QVERIFY(!key.isNull()); // null passphrase => should be able to decode key
+ }
+ {
+ if (!keyFile.isOpen())
+ keyFile.open(QIODevice::ReadOnly);
+ else
+ keyFile.reset();
+ QSslKey key(&keyFile,QSsl::Rsa,QSsl::Pem, QSsl::PrivateKey, "");
+ QVERIFY(!key.isNull()); // empty passphrase => should be able to decode key
+ }
+ {
+ if (!keyFile.isOpen())
+ keyFile.open(QIODevice::ReadOnly);
+ else
+ keyFile.reset();
+ QSslKey key(&keyFile,QSsl::Rsa,QSsl::Pem, QSsl::PrivateKey, "xxx");
+ QVERIFY(!key.isNull()); // passphrase given but key is not encrypted anyway => should work
+ }
+ }
+}
+
+#endif
+
+QTEST_MAIN(tst_QSslKey)
+#include "tst_qsslkey.moc"
diff --git a/tests/auto/network/ssl/qsslsocket/.gitignore b/tests/auto/network/ssl/qsslsocket/.gitignore
new file mode 100644
index 0000000000..f2319a97eb
--- /dev/null
+++ b/tests/auto/network/ssl/qsslsocket/.gitignore
@@ -0,0 +1 @@
+tst_qsslsocket
diff --git a/tests/auto/network/ssl/qsslsocket/certs/aspiriniks.ca.crt b/tests/auto/network/ssl/qsslsocket/certs/aspiriniks.ca.crt
new file mode 100644
index 0000000000..36436b6248
--- /dev/null
+++ b/tests/auto/network/ssl/qsslsocket/certs/aspiriniks.ca.crt
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDnDCCAoQCCQDV3otC4hs2KTANBgkqhkiG9w0BAQUFADCBjzELMAkGA1UEBhMC
+Tk8xDTALBgNVBAgTBE9zbG8xDTALBgNVBAcTBE9zbG8xDzANBgNVBAoTBlRUIEFT
+QTEOMAwGA1UECxMFUVQgU1cxHDAaBgNVBAMTE2FzcGlyaW5pa3MudHJvbGwubm8x
+IzAhBgkqhkiG9w0BCQEWFGFiYWJpY0B0cm9sbHRlY2guY29tMB4XDTA4MTEwMTA4
+NTcyOFoXDTA5MTEwMTA4NTcyOFowgY8xCzAJBgNVBAYTAk5PMQ0wCwYDVQQIEwRP
+c2xvMQ0wCwYDVQQHEwRPc2xvMQ8wDQYDVQQKEwZUVCBBU0ExDjAMBgNVBAsTBVFU
+IFNXMRwwGgYDVQQDExNhc3BpcmluaWtzLnRyb2xsLm5vMSMwIQYJKoZIhvcNAQkB
+FhRhYmFiaWNAdHJvbGx0ZWNoLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAMV2bMD1DN3DMgbxU3DXw2i7EWGDXcWjTDtdHvqgIb+9nHqo3MJSrzJy
+qgEPoOsXqswMla9wDPZAsWv5gVAmVSqpy2lfEgfY7LaSHiGD75seF7zIy+CxREHW
+DofHXpJGGJpBCZEKQt2HfHu3+yAYNPucN78tWNZAcPbUg5tfxMZeepRimAZNIxBI
+93SDrl/f9Ka7hvPSzUQsnp8hfdpHlFPFznKfD6yPrjxgz2mT9efavJ4DhtyIa4m+
+paiX515CidDz4A8CFxKZbYvuqq1ilibF/si2so9VhALC77ZcAJP1IMuT8T+WUCxq
+skJqiSCncl0Hgr+ba8MDGF9UQYowgjMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
+KcJuNUHvjB8ok3cnTmQEeF0LPPkgj28Tqb5TFB8xpVfRI+wvTYsHsmGdOKCgYJ3a
+7VflIsr63ojG8/rXK8H/cx2o2f2Hr3liJdi1UnoLDDRjBqGGz7JNuMreYokPvIbm
+eP01mVyK4PO2iYRwHUIAw5eeB1vMWKX2z95MupD+HRLtmGyaLALg8aQxj5N84Ewl
+eU2PQfhv8A1wj7aL17kfEUxDerQ1kUzlThJMV1J8Dl0l4C9N8evQkelROJU00i46
+oJikA8BW6EpgbnGyNyyj5Loy4wLPKew9nTS8MCJ5xPMQc0urbY/VzuOeUK7WQof7
+xOFSsRAVyQv+yqgmcZMCtg==
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslsocket/certs/fake-login.live.com.key b/tests/auto/network/ssl/qsslsocket/certs/fake-login.live.com.key
new file mode 100644
index 0000000000..692a7bd85d
--- /dev/null
+++ b/tests/auto/network/ssl/qsslsocket/certs/fake-login.live.com.key
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQDOtxdvMa0VHUQYG5q7Tsi1Jj4qKEJppyZEkmuRXOi0fDbd1SwE
+bwHrLGMvDO6OMrYBbq3WDNrtnIfF9CvzUOEch+gjr4hEVQqecU5fb45Wor7yNel3
+/C/gxfbzuXHrsj/gUjNghL2i10+c2NW+hUo/sWO6OusaBT6d6s7ee+YBcQIDAQAB
+AoGAb8cVhu0HuLkgjyCuJMbPRRUu3ED02Iin6sB6JhplQuNAD+grayJTmUVhRJnr
+jTziqhedLHe7Em1oBaSo92MutfMpXvWiccSlbNygI61VgmrJpVB+qIN5H9cQc9ql
+Zymc+nIPa1+i5rsrOzlpUytTh7AsbZ27QG4tQXR/kQejEiECQQD6BgTxBeT8D7x9
+DuukoBaSCkLwx7U7P1NXx15EI3lA1nO51t6UHfvk/jGPp8Sl4wv4alJ7AQxr5uQ/
+vC3kzA/1AkEA06gNu10se8pe3n8qL2RRt+FmVjHkQdD9Mm2Dx9oWCs2A4wOSOrlo
+6/nKYF1CaQNYn9HgsNbHVEUpnICVO18qDQJBALEw/uOJ1+TDikPfBSWgxx4s45Ad
+GNWqZXh6NNZ5hX9r/IwiOZAjR9fcRmeW8IjYRi2BvH6sGY+HDRAWXzgdXtkCQCma
+dOiJTf8fLjqp4E7kdzOfuI/kyqstOze4Uxjrgz2oW1dEEnA8laUcumzqp+0gXUE8
+7d+UuCWWWrGKjMrYz9kCQQDh5E5+b6Djn082Jo6gvyuXWC5eXju6IdmihlJ2SMzD
+s2y3IDjOUtTeQQRDymLneteMz0ha79KeUp6VnAvZCOVe
+-----END RSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslsocket/certs/fake-login.live.com.pem b/tests/auto/network/ssl/qsslsocket/certs/fake-login.live.com.pem
new file mode 100644
index 0000000000..429f95187c
--- /dev/null
+++ b/tests/auto/network/ssl/qsslsocket/certs/fake-login.live.com.pem
@@ -0,0 +1,19 @@
+-----BEGIN CERTIFICATE-----
+MIIDDjCCAnegAwIBAgIRALC3Ez7Qlvm1b66RyHS9OsAwDQYJKoZIhvcNAQEFBQAw
+XjELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGElu
+dGVybmV0IFdpZGdpdHMgUHR5IEx0ZDEXMBUGA1UEAxMObG9naW4ubGl2ZS5jb20w
+HhcNMTEwMzI1MTMyODUwWhcNMTEwNDI0MTMyODUwWjBeMQswCQYDVQQGEwJBVTET
+MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
+dHkgTHRkMRcwFQYDVQQDEw5sb2dpbi5saXZlLmNvbTCBnzANBgkqhkiG9w0BAQEF
+AAOBjQAwgYkCgYEAzrcXbzGtFR1EGBuau07ItSY+KihCaacmRJJrkVzotHw23dUs
+BG8B6yxjLwzujjK2AW6t1gza7ZyHxfQr81DhHIfoI6+IRFUKnnFOX2+OVqK+8jXp
+d/wv4MX287lx67I/4FIzYIS9otdPnNjVvoVKP7FjujrrGgU+nerO3nvmAXECAwEA
+AaOByzCByDAdBgNVHQ4EFgQUpSOEcmtkQITvBdM2IDfcXnJ0FCAwgZgGA1UdIwSB
+kDCBjYAUpSOEcmtkQITvBdM2IDfcXnJ0FCChYqRgMF4xCzAJBgNVBAYTAkFVMRMw
+EQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0
+eSBMdGQxFzAVBgNVBAMTDmxvZ2luLmxpdmUuY29tghEAsLcTPtCW+bVvrpHIdL06
+wDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GBAD+2HT4GSHHKCdbl9VkX
+zsl+D+drMm2b0ksxz9SgPihP7aW50EEIJDEEihNMTa27mhpeOXHc/sLqDi4ECUao
+/0Ns/5uoVuAIrAKCydmtPsonVFh9XWjyrfUzPOHAc9p2bmJ1i9a3kTsLB6jlrVDO
+VufGzsowHlHZ0TtKf5omojU5
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslsocket/certs/fluke.cert b/tests/auto/network/ssl/qsslsocket/certs/fluke.cert
new file mode 100644
index 0000000000..069fa6b341
--- /dev/null
+++ b/tests/auto/network/ssl/qsslsocket/certs/fluke.cert
@@ -0,0 +1,75 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 0 (0x0)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=NO, ST=Oslo, L=Nydalen, O=Nokia Corporation and/or its subsidiary(-ies), OU=Development, CN=fluke.troll.no/emailAddress=ahanssen@trolltech.com
+ Validity
+ Not Before: Dec 4 01:10:32 2007 GMT
+ Not After : Apr 21 01:10:32 2035 GMT
+ Subject: C=NO, ST=Oslo, O=Nokia Corporation and/or its subsidiary(-ies), OU=Development, CN=fluke.troll.no
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public Key: (1024 bit)
+ Modulus (1024 bit):
+ 00:a7:c8:a0:4a:c4:19:05:1b:66:ba:32:e2:d2:f1:
+ 1c:6f:17:82:e4:39:2e:01:51:90:db:04:34:32:11:
+ 21:c2:0d:6f:59:d8:53:90:54:3f:83:8f:a9:d3:b3:
+ d5:ee:1a:9b:80:ae:c3:25:c9:5e:a5:af:4b:60:05:
+ aa:a0:d1:91:01:1f:ca:04:83:e3:58:1c:99:32:45:
+ 84:70:72:58:03:98:4a:63:8b:41:f5:08:49:d2:91:
+ 02:60:6b:e4:64:fe:dd:a0:aa:74:08:e9:34:4c:91:
+ 5f:12:3d:37:4d:54:2c:ad:7f:5b:98:60:36:02:8c:
+ 3b:f6:45:f3:27:6a:9b:94:9d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 21:85:04:3D:23:01:66:E5:F7:9F:1A:84:24:8A:AF:0A:79:F4:E5:AC
+ X509v3 Authority Key Identifier:
+ DirName:/C=NO/ST=Oslo/L=Nydalen/O=Nokia Corporation and/or its subsidiary(-ies)/OU=Development/CN=fluke.troll.no/emailAddress=ahanssen@trolltech.com
+ serial:8E:A8:B4:E8:91:B7:54:2E
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 6d:57:5f:d1:05:43:f0:62:05:ec:2a:71:a5:dc:19:08:f2:c4:
+ a6:bd:bb:25:d9:ca:89:01:0e:e4:cf:1f:c1:8c:c8:24:18:35:
+ 53:59:7b:c0:43:b4:32:e6:98:b2:a6:ef:15:05:0b:48:5f:e1:
+ a0:0c:97:a9:a1:77:d8:35:18:30:bc:a9:8f:d3:b7:54:c7:f1:
+ a9:9e:5d:e6:19:bf:f6:3c:5b:2b:d8:e4:3e:62:18:88:8b:d3:
+ 24:e1:40:9b:0c:e6:29:16:62:ab:ea:05:24:70:36:aa:55:93:
+ ef:02:81:1b:23:10:a2:04:eb:56:95:75:fc:f8:94:b1:5d:42:
+ c5:3f:36:44:85:5d:3a:2e:90:46:8a:a2:b9:6f:87:ae:0c:15:
+ 40:19:31:90:fc:3b:25:bb:ae:f1:66:13:0d:85:90:d9:49:34:
+ 8f:f2:5d:f9:7a:db:4d:5d:27:f6:76:9d:35:8c:06:a6:4c:a3:
+ b1:b2:b6:6f:1d:d7:a3:00:fd:72:eb:9e:ea:44:a1:af:21:34:
+ 7d:c7:42:e2:49:91:19:8b:c0:ad:ba:82:80:a8:71:70:f4:35:
+ 31:91:63:84:20:95:e9:60:af:64:8b:cc:ff:3d:8a:76:74:3d:
+ c8:55:6d:e4:8e:c3:2b:1c:e8:42:18:ae:9f:e6:6b:9c:34:06:
+ ec:6a:f2:c3
+-----BEGIN CERTIFICATE-----
+MIIEEzCCAvugAwIBAgIBADANBgkqhkiG9w0BAQUFADCBnDELMAkGA1UEBhMCTk8x
+DTALBgNVBAgTBE9zbG8xEDAOBgNVBAcTB055ZGFsZW4xFjAUBgNVBAoTDVRyb2xs
+dGVjaCBBU0ExFDASBgNVBAsTC0RldmVsb3BtZW50MRcwFQYDVQQDEw5mbHVrZS50
+cm9sbC5ubzElMCMGCSqGSIb3DQEJARYWYWhhbnNzZW5AdHJvbGx0ZWNoLmNvbTAe
+Fw0wNzEyMDQwMTEwMzJaFw0zNTA0MjEwMTEwMzJaMGMxCzAJBgNVBAYTAk5PMQ0w
+CwYDVQQIEwRPc2xvMRYwFAYDVQQKEw1Ucm9sbHRlY2ggQVNBMRQwEgYDVQQLEwtE
+ZXZlbG9wbWVudDEXMBUGA1UEAxMOZmx1a2UudHJvbGwubm8wgZ8wDQYJKoZIhvcN
+AQEBBQADgY0AMIGJAoGBAKfIoErEGQUbZroy4tLxHG8XguQ5LgFRkNsENDIRIcIN
+b1nYU5BUP4OPqdOz1e4am4CuwyXJXqWvS2AFqqDRkQEfygSD41gcmTJFhHByWAOY
+SmOLQfUISdKRAmBr5GT+3aCqdAjpNEyRXxI9N01ULK1/W5hgNgKMO/ZF8ydqm5Sd
+AgMBAAGjggEaMIIBFjAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NM
+IEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUIYUEPSMBZuX3nxqEJIqv
+Cnn05awwgbsGA1UdIwSBszCBsKGBoqSBnzCBnDELMAkGA1UEBhMCTk8xDTALBgNV
+BAgTBE9zbG8xEDAOBgNVBAcTB055ZGFsZW4xFjAUBgNVBAoTDVRyb2xsdGVjaCBB
+U0ExFDASBgNVBAsTC0RldmVsb3BtZW50MRcwFQYDVQQDEw5mbHVrZS50cm9sbC5u
+bzElMCMGCSqGSIb3DQEJARYWYWhhbnNzZW5AdHJvbGx0ZWNoLmNvbYIJAI6otOiR
+t1QuMA0GCSqGSIb3DQEBBQUAA4IBAQBtV1/RBUPwYgXsKnGl3BkI8sSmvbsl2cqJ
+AQ7kzx/BjMgkGDVTWXvAQ7Qy5piypu8VBQtIX+GgDJepoXfYNRgwvKmP07dUx/Gp
+nl3mGb/2PFsr2OQ+YhiIi9Mk4UCbDOYpFmKr6gUkcDaqVZPvAoEbIxCiBOtWlXX8
++JSxXULFPzZEhV06LpBGiqK5b4euDBVAGTGQ/Dslu67xZhMNhZDZSTSP8l35ettN
+XSf2dp01jAamTKOxsrZvHdejAP1y657qRKGvITR9x0LiSZEZi8CtuoKAqHFw9DUx
+kWOEIJXpYK9ki8z/PYp2dD3IVW3kjsMrHOhCGK6f5mucNAbsavLD
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslsocket/certs/fluke.key b/tests/auto/network/ssl/qsslsocket/certs/fluke.key
new file mode 100644
index 0000000000..9d1664d609
--- /dev/null
+++ b/tests/auto/network/ssl/qsslsocket/certs/fluke.key
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQCnyKBKxBkFG2a6MuLS8RxvF4LkOS4BUZDbBDQyESHCDW9Z2FOQ
+VD+Dj6nTs9XuGpuArsMlyV6lr0tgBaqg0ZEBH8oEg+NYHJkyRYRwclgDmEpji0H1
+CEnSkQJga+Rk/t2gqnQI6TRMkV8SPTdNVCytf1uYYDYCjDv2RfMnapuUnQIDAQAB
+AoGANFzLkanTeSGNFM0uttBipFT9F4a00dqHz6JnO7zXAT26I5r8sU1pqQBb6uLz
+/+Qz5Zwk8RUAQcsMRgJetuPQUb0JZjF6Duv24hNazqXBCu7AZzUenjafwmKC/8ri
+KpX3fTwqzfzi//FKGgbXQ80yykSSliDL3kn/drATxsLCgQECQQDXhEFWLJ0vVZ1s
+1Ekf+3NITE+DR16X+LQ4W6vyEHAjTbaNWtcTKdAWLA2l6N4WAAPYSi6awm+zMxx4
+VomVTsjdAkEAx0z+e7natLeFcrrq8pbU+wa6SAP1VfhQWKitxL1e7u/QO90NCpxE
+oQYKzMkmmpOOFjQwEMAy1dvFMbm4LHlewQJAC/ksDBaUcQHHqjktCtrUb8rVjAyW
+A8lscckeB2fEYyG5J6dJVaY4ClNOOs5yMDS2Afk1F6H/xKvtQ/5CzInA/QJATDub
+K+BPU8jO9q+gpuIi3VIZdupssVGmCgObVCHLakG4uO04y9IyPhV9lA9tALtoIf4c
+VIvv5fWGXBrZ48kZAQJBAJmVCdzQxd9LZI5vxijUCj5EI4e+x5DRqVUvyP8KCZrC
+AiNyoDP85T+hBZaSXK3aYGpVwelyj3bvo1GrTNwNWLw=
+-----END RSA PRIVATE KEY-----
diff --git a/tests/auto/network/ssl/qsslsocket/certs/qt-test-server-cacert.pem b/tests/auto/network/ssl/qsslsocket/certs/qt-test-server-cacert.pem
new file mode 100644
index 0000000000..25bd4046e8
--- /dev/null
+++ b/tests/auto/network/ssl/qsslsocket/certs/qt-test-server-cacert.pem
@@ -0,0 +1,17 @@
+-----BEGIN CERTIFICATE-----
+MIICrTCCAhYCCQCdDn5rci6VDjANBgkqhkiG9w0BAQQFADCBmjEOMAwGA1UEChMF
+Tm9raWExFDASBgNVBAsTC1F0IFNvZnR3YXJlMSIwIAYJKoZIhvcNAQkBFhNub2Jv
+ZHlAbm9kb21haW4ub3JnMQ0wCwYDVQQHEwRPc2xvMQ0wCwYDVQQIEwRPc2xvMQsw
+CQYDVQQGEwJOTzEjMCEGA1UEAxMacXQtdGVzdC1zZXJ2ZXIucXQtdGVzdC1uZXQw
+HhcNMDkwNzEwMDc0MTIzWhcNMTkwNzA4MDc0MTIzWjCBmjEOMAwGA1UEChMFTm9r
+aWExFDASBgNVBAsTC1F0IFNvZnR3YXJlMSIwIAYJKoZIhvcNAQkBFhNub2JvZHlA
+bm9kb21haW4ub3JnMQ0wCwYDVQQHEwRPc2xvMQ0wCwYDVQQIEwRPc2xvMQswCQYD
+VQQGEwJOTzEjMCEGA1UEAxMacXQtdGVzdC1zZXJ2ZXIucXQtdGVzdC1uZXQwgZ8w
+DQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM2q22/WNMmn8cC+5EEYGeICySLmp9W6
+Ay6eKHr0Xxp3X3epETuPfvAuxp7rOtkS18EMUegkUj8jw0IMEcbyHKFC/rTCaYOt
+93CxGBXMIChiMPAsFeYzGa/D6xzAkfcRaJRQ+Ek3CDLXPnXfo7xpABXezYcPXAJr
+gsgBfWrwHdxzAgMBAAEwDQYJKoZIhvcNAQEEBQADgYEAy7YOLCZABQy2Ygkchq1I
++TUpvMn+gLwAyW8TNErM1V4lNY2+K78RawzKx3SqM97ymCy4TD45EA3A2gmi32NI
+xSKBNjFyzngUqsXBdcSasALiowlZCiJrGwlGX5qCkBlxXvJeUEbuJLPYVl5FBjXZ
+6o00K4cSPCqtqUez7WSmDZU=
+-----END CERTIFICATE-----
diff --git a/tests/auto/network/ssl/qsslsocket/qsslsocket.pro b/tests/auto/network/ssl/qsslsocket/qsslsocket.pro
new file mode 100644
index 0000000000..1f5c7f6aaf
--- /dev/null
+++ b/tests/auto/network/ssl/qsslsocket/qsslsocket.pro
@@ -0,0 +1,48 @@
+load(qttest_p4)
+
+SOURCES += tst_qsslsocket.cpp
+!wince*:win32:LIBS += -lws2_32
+QT += core-private network-private
+QT -= gui
+
+TARGET = tst_qsslsocket
+
+win32 {
+ CONFIG(debug, debug|release) {
+ DESTDIR = debug
+} else {
+ DESTDIR = release
+ }
+}
+
+# OpenSSL support
+contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) {
+ symbian {
+ INCLUDEPATH *= $$OS_LAYER_SSL_SYSTEMINCLUDE
+ } else {
+ include($$QT_SOURCE_TREE/config.tests/unix/openssl/openssl.pri)
+ }
+ # Add optional SSL libs
+ LIBS += $$OPENSSL_LIBS
+}
+
+wince* {
+ DEFINES += SRCDIR=\\\"./\\\"
+
+ certFiles.files = certs ssl.tar.gz
+ certFiles.path = .
+ DEPLOYMENT += certFiles
+} else:symbian {
+ DEFINES += QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
+ TARGET.EPOCHEAPSIZE="0x100 0x3000000"
+ TARGET.CAPABILITY=NetworkServices ReadUserData
+
+ certFiles.files = certs ssl.tar.gz
+ certFiles.path = .
+ DEPLOYMENT += certFiles
+ INCLUDEPATH *= $$MW_LAYER_SYSTEMINCLUDE # Needed for e32svr.h in S^3 envs
+} else {
+ DEFINES += SRCDIR=\\\"$$PWD/\\\"
+}
+
+requires(contains(QT_CONFIG,private_tests))
diff --git a/tests/auto/network/ssl/qsslsocket/ssl.tar.gz b/tests/auto/network/ssl/qsslsocket/ssl.tar.gz
new file mode 100644
index 0000000000..b59af51f46
--- /dev/null
+++ b/tests/auto/network/ssl/qsslsocket/ssl.tar.gz
Binary files differ
diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
new file mode 100644
index 0000000000..6b7720308d
--- /dev/null
+++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
@@ -0,0 +1,2097 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtCore/qthread.h>
+#include <QtNetwork/qhostaddress.h>
+#include <QtNetwork/qhostinfo.h>
+#include <QtNetwork/qnetworkproxy.h>
+#include <QtNetwork/qsslcipher.h>
+#include <QtNetwork/qsslconfiguration.h>
+#include <QtNetwork/qsslkey.h>
+#include <QtNetwork/qsslsocket.h>
+#include <QtNetwork/qtcpserver.h>
+#include <QtTest/QtTest>
+
+#include <QNetworkProxy>
+#include <QAuthenticator>
+
+#include "private/qhostinfo_p.h"
+#ifndef QT_NO_OPENSSL
+#include "private/qsslsocket_openssl_p.h"
+#include "private/qsslsocket_openssl_symbols_p.h"
+#endif
+
+#include "../../../network-settings.h"
+
+Q_DECLARE_METATYPE(QAbstractSocket::SocketState)
+Q_DECLARE_METATYPE(QAbstractSocket::SocketError)
+#ifndef QT_NO_OPENSSL
+Q_DECLARE_METATYPE(QSslSocket::SslMode)
+typedef QList<QSslError::SslError> SslErrorList;
+Q_DECLARE_METATYPE(SslErrorList)
+Q_DECLARE_METATYPE(QSslError)
+Q_DECLARE_METATYPE(QSsl::SslProtocol)
+Q_DECLARE_METATYPE(QSslConfiguration)
+#endif
+
+#if defined Q_OS_HPUX && defined Q_CC_GNU
+// This error is delivered every time we try to use the fluke CA
+// certificate. For now we work around this bug. Task 202317.
+#define QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
+#endif
+
+#ifdef Q_OS_SYMBIAN
+#define SRCDIR ""
+#endif
+
+#ifndef QT_NO_OPENSSL
+class QSslSocketPtr: public QSharedPointer<QSslSocket>
+{
+public:
+ inline QSslSocketPtr(QSslSocket *ptr = 0)
+ : QSharedPointer<QSslSocket>(ptr)
+ { }
+
+ inline operator QSslSocket *() const { return data(); }
+};
+#endif
+
+class tst_QSslSocket : public QObject
+{
+ Q_OBJECT
+
+ int proxyAuthCalled;
+
+public:
+ tst_QSslSocket();
+ virtual ~tst_QSslSocket();
+
+ static void enterLoop(int secs)
+ {
+ ++loopLevel;
+ QTestEventLoop::instance().enterLoop(secs);
+ }
+
+ static bool timeout()
+ {
+ return QTestEventLoop::instance().timeout();
+ }
+
+#ifndef QT_NO_OPENSSL
+ QSslSocketPtr newSocket();
+#endif
+
+public slots:
+ void initTestCase_data();
+ void init();
+ void cleanup();
+ void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth);
+
+#ifndef QT_NO_OPENSSL
+private slots:
+ void constructing();
+ void simpleConnect();
+ void simpleConnectWithIgnore();
+
+ // API tests
+ void sslErrors_data();
+ void sslErrors();
+ void addCaCertificate();
+ void addCaCertificates();
+ void addCaCertificates2();
+ void ciphers();
+ void connectToHostEncrypted();
+ void connectToHostEncryptedWithVerificationPeerName();
+ void sessionCipher();
+ void flush();
+ void isEncrypted();
+ void localCertificate();
+ void mode();
+ void peerCertificate();
+ void peerCertificateChain();
+ void privateKey();
+ void privateKeyOpaque();
+ void protocol();
+ void protocolServerSide_data();
+ void protocolServerSide();
+ void setCaCertificates();
+ void setLocalCertificate();
+ void setPrivateKey();
+ void setSocketDescriptor();
+ void setSslConfiguration_data();
+ void setSslConfiguration();
+ void waitForEncrypted();
+ void waitForEncryptedMinusOne();
+ void waitForConnectedEncryptedReadyRead();
+ void startClientEncryption();
+ void startServerEncryption();
+ void addDefaultCaCertificate();
+ void addDefaultCaCertificates();
+ void addDefaultCaCertificates2();
+ void defaultCaCertificates();
+ void defaultCiphers();
+ void resetDefaultCiphers();
+ void setDefaultCaCertificates();
+ void setDefaultCiphers();
+ void supportedCiphers();
+ void systemCaCertificates();
+ void wildcardCertificateNames();
+ void wildcard();
+ void setEmptyKey();
+ void spontaneousWrite();
+ void setReadBufferSize();
+ void setReadBufferSize_task_250027();
+ void waitForMinusOne();
+ void verifyMode();
+ void verifyDepth();
+ void peerVerifyError();
+ void disconnectFromHostWhenConnecting();
+ void disconnectFromHostWhenConnected();
+ void resetProxy();
+ void ignoreSslErrorsList_data();
+ void ignoreSslErrorsList();
+ void ignoreSslErrorsListWithSlot_data();
+ void ignoreSslErrorsListWithSlot();
+ void readFromClosedSocket();
+ void writeBigChunk();
+ void blacklistedCertificates();
+ void setEmptyDefaultConfiguration();
+ void versionAccessors();
+
+ static void exitLoop()
+ {
+ // Safe exit - if we aren't in an event loop, don't
+ // exit one.
+ if (loopLevel > 0) {
+ --loopLevel;
+ QTestEventLoop::instance().exitLoop();
+ }
+ }
+
+protected slots:
+ void ignoreErrorSlot()
+ {
+ socket->ignoreSslErrors();
+ }
+ void untrustedWorkaroundSlot(const QList<QSslError> &errors)
+ {
+ if (errors.size() == 1 &&
+ (errors.first().error() == QSslError::CertificateUntrusted ||
+ errors.first().error() == QSslError::SelfSignedCertificate))
+ socket->ignoreSslErrors();
+ }
+ void ignoreErrorListSlot(const QList<QSslError> &errors);
+
+private:
+ QSslSocket *socket;
+ QList<QSslError> storedExpectedSslErrors;
+#endif // QT_NO_OPENSSL
+private:
+ static int loopLevel;
+};
+
+int tst_QSslSocket::loopLevel = 0;
+
+tst_QSslSocket::tst_QSslSocket()
+{
+#ifndef QT_NO_OPENSSL
+ qRegisterMetaType<QList<QSslError> >("QList<QSslError>");
+ qRegisterMetaType<QSslError>("QSslError");
+ qRegisterMetaType<QAbstractSocket::SocketState>("QAbstractSocket::SocketState");
+ qRegisterMetaType<QAbstractSocket::SocketError>("QAbstractSocket::SocketError");
+ qRegisterMetaType<QAbstractSocket::SocketState>("QSslSocket::SslMode");
+#endif
+ Q_SET_DEFAULT_IAP
+}
+
+tst_QSslSocket::~tst_QSslSocket()
+{
+}
+
+enum ProxyTests {
+ NoProxy = 0x00,
+ Socks5Proxy = 0x01,
+ HttpProxy = 0x02,
+ TypeMask = 0x0f,
+
+ NoAuth = 0x00,
+ AuthBasic = 0x10,
+ AuthNtlm = 0x20,
+ AuthMask = 0xf0
+};
+
+void tst_QSslSocket::initTestCase_data()
+{
+ QTest::addColumn<bool>("setProxy");
+ QTest::addColumn<int>("proxyType");
+
+ QTest::newRow("WithoutProxy") << false << 0;
+ QTest::newRow("WithSocks5Proxy") << true << int(Socks5Proxy);
+ QTest::newRow("WithSocks5ProxyAuth") << true << int(Socks5Proxy | AuthBasic);
+
+ QTest::newRow("WithHttpProxy") << true << int(HttpProxy);
+ QTest::newRow("WithHttpProxyBasicAuth") << true << int(HttpProxy | AuthBasic);
+ // uncomment the line below when NTLM works
+// QTest::newRow("WithHttpProxyNtlmAuth") << true << int(HttpProxy | AuthNtlm);
+}
+
+void tst_QSslSocket::init()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy) {
+ QFETCH_GLOBAL(int, proxyType);
+ QString fluke = QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString();
+ QNetworkProxy proxy;
+
+ switch (proxyType) {
+ case Socks5Proxy:
+ proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, fluke, 1080);
+ break;
+
+ case Socks5Proxy | AuthBasic:
+ proxy = QNetworkProxy(QNetworkProxy::Socks5Proxy, fluke, 1081);
+ break;
+
+ case HttpProxy | NoAuth:
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3128);
+ break;
+
+ case HttpProxy | AuthBasic:
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3129);
+ break;
+
+ case HttpProxy | AuthNtlm:
+ proxy = QNetworkProxy(QNetworkProxy::HttpProxy, fluke, 3130);
+ break;
+ }
+ QNetworkProxy::setApplicationProxy(proxy);
+ }
+
+ qt_qhostinfo_clear_cache();
+}
+
+void tst_QSslSocket::cleanup()
+{
+ QNetworkProxy::setApplicationProxy(QNetworkProxy::DefaultProxy);
+}
+
+#ifndef QT_NO_OPENSSL
+QSslSocketPtr tst_QSslSocket::newSocket()
+{
+ QSslSocket *socket = new QSslSocket;
+
+ proxyAuthCalled = 0;
+ connect(socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
+ SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
+ Qt::DirectConnection);
+
+ return QSslSocketPtr(socket);
+}
+#endif
+
+void tst_QSslSocket::proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *auth)
+{
+ ++proxyAuthCalled;
+ auth->setUser("qsockstest");
+ auth->setPassword("password");
+}
+
+#ifndef QT_NO_OPENSSL
+
+void tst_QSslSocket::constructing()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QSslSocket socket;
+
+ QCOMPARE(socket.state(), QSslSocket::UnconnectedState);
+ QCOMPARE(socket.mode(), QSslSocket::UnencryptedMode);
+ QVERIFY(!socket.isEncrypted());
+ QCOMPARE(socket.bytesAvailable(), qint64(0));
+ QCOMPARE(socket.bytesToWrite(), qint64(0));
+ QVERIFY(!socket.canReadLine());
+ QVERIFY(socket.atEnd());
+ QCOMPARE(socket.localCertificate(), QSslCertificate());
+ QCOMPARE(socket.sslConfiguration(), QSslConfiguration::defaultConfiguration());
+ QCOMPARE(socket.errorString(), QString("Unknown error"));
+ char c = '\0';
+ QVERIFY(!socket.getChar(&c));
+ QCOMPARE(c, '\0');
+ QVERIFY(!socket.isOpen());
+ QVERIFY(!socket.isReadable());
+ QVERIFY(socket.isSequential());
+ QVERIFY(!socket.isTextModeEnabled());
+ QVERIFY(!socket.isWritable());
+ QCOMPARE(socket.openMode(), QIODevice::NotOpen);
+ QVERIFY(socket.peek(2).isEmpty());
+ QCOMPARE(socket.pos(), qint64(0));
+ QVERIFY(!socket.putChar('c'));
+ QVERIFY(socket.read(2).isEmpty());
+ QCOMPARE(socket.read(0, 0), qint64(-1));
+ QVERIFY(socket.readAll().isEmpty());
+ QTest::ignoreMessage(QtWarningMsg, "QIODevice::readLine: Called with maxSize < 2");
+ QCOMPARE(socket.readLine(0, 0), qint64(-1));
+ char buf[10];
+ QCOMPARE(socket.readLine(buf, sizeof(buf)), qint64(-1));
+ QTest::ignoreMessage(QtWarningMsg, "QIODevice::seek: The device is not open");
+ QVERIFY(!socket.reset());
+ QTest::ignoreMessage(QtWarningMsg, "QIODevice::seek: The device is not open");
+ QVERIFY(!socket.seek(2));
+ QCOMPARE(socket.size(), qint64(0));
+ QVERIFY(!socket.waitForBytesWritten(10));
+ QVERIFY(!socket.waitForReadyRead(10));
+ QCOMPARE(socket.write(0, 0), qint64(-1));
+ QCOMPARE(socket.write(QByteArray()), qint64(-1));
+ QCOMPARE(socket.error(), QAbstractSocket::UnknownSocketError);
+ QVERIFY(!socket.flush());
+ QVERIFY(!socket.isValid());
+ QCOMPARE(socket.localAddress(), QHostAddress());
+ QCOMPARE(socket.localPort(), quint16(0));
+ QCOMPARE(socket.peerAddress(), QHostAddress());
+ QVERIFY(socket.peerName().isEmpty());
+ QCOMPARE(socket.peerPort(), quint16(0));
+ QCOMPARE(socket.proxy().type(), QNetworkProxy::DefaultProxy);
+ QCOMPARE(socket.readBufferSize(), qint64(0));
+ QCOMPARE(socket.socketDescriptor(), -1);
+ QCOMPARE(socket.socketType(), QAbstractSocket::TcpSocket);
+ QVERIFY(!socket.waitForConnected(10));
+ QTest::ignoreMessage(QtWarningMsg, "QSslSocket::waitForDisconnected() is not allowed in UnconnectedState");
+ QVERIFY(!socket.waitForDisconnected(10));
+ QCOMPARE(socket.protocol(), QSsl::SecureProtocols);
+
+ QSslConfiguration savedDefault = QSslConfiguration::defaultConfiguration();
+
+ // verify that changing the default config doesn't affect this socket
+ // (on Unix, the ca certs might be empty, depending on whether we load
+ // them on demand or not, so set them explicitly)
+ socket.setCaCertificates(QSslSocket::systemCaCertificates());
+ QSslSocket::setDefaultCaCertificates(QList<QSslCertificate>());
+ QSslSocket::setDefaultCiphers(QList<QSslCipher>());
+ QVERIFY(!socket.caCertificates().isEmpty());
+ QVERIFY(!socket.ciphers().isEmpty());
+
+ // verify the default as well:
+ QVERIFY(QSslConfiguration::defaultConfiguration().caCertificates().isEmpty());
+ QVERIFY(QSslConfiguration::defaultConfiguration().ciphers().isEmpty());
+
+ QSslConfiguration::setDefaultConfiguration(savedDefault);
+}
+
+void tst_QSslSocket::simpleConnect()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ QSslSocket socket;
+ QSignalSpy connectedSpy(&socket, SIGNAL(connected()));
+ QSignalSpy hostFoundSpy(&socket, SIGNAL(hostFound()));
+ QSignalSpy disconnectedSpy(&socket, SIGNAL(disconnected()));
+ QSignalSpy connectionEncryptedSpy(&socket, SIGNAL(encrypted()));
+ QSignalSpy sslErrorsSpy(&socket, SIGNAL(sslErrors(const QList<QSslError> &)));
+
+ connect(&socket, SIGNAL(connected()), this, SLOT(exitLoop()));
+ connect(&socket, SIGNAL(disconnected()), this, SLOT(exitLoop()));
+ connect(&socket, SIGNAL(modeChanged(QSslSocket::SslMode)), this, SLOT(exitLoop()));
+ connect(&socket, SIGNAL(encrypted()), this, SLOT(exitLoop()));
+ connect(&socket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(exitLoop()));
+ connect(&socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(exitLoop()));
+
+ // Start connecting
+ socket.connectToHost(QtNetworkSettings::serverName(), 993);
+ QCOMPARE(socket.state(), QAbstractSocket::HostLookupState);
+ enterLoop(10);
+
+ // Entered connecting state
+#ifndef Q_OS_SYMBIAN
+ QCOMPARE(socket.state(), QAbstractSocket::ConnectingState);
+ QCOMPARE(connectedSpy.count(), 0);
+#endif
+ QCOMPARE(hostFoundSpy.count(), 1);
+ QCOMPARE(disconnectedSpy.count(), 0);
+ enterLoop(10);
+
+ // Entered connected state
+ QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
+ QCOMPARE(socket.mode(), QSslSocket::UnencryptedMode);
+ QVERIFY(!socket.isEncrypted());
+ QCOMPARE(connectedSpy.count(), 1);
+ QCOMPARE(hostFoundSpy.count(), 1);
+ QCOMPARE(disconnectedSpy.count(), 0);
+
+ // Enter encrypted mode
+ socket.startClientEncryption();
+ QCOMPARE(socket.mode(), QSslSocket::SslClientMode);
+ QVERIFY(!socket.isEncrypted());
+ QCOMPARE(connectionEncryptedSpy.count(), 0);
+ QCOMPARE(sslErrorsSpy.count(), 0);
+
+ // Starting handshake
+ enterLoop(10);
+ QCOMPARE(sslErrorsSpy.count(), 1);
+ QCOMPARE(connectionEncryptedSpy.count(), 0);
+ QVERIFY(!socket.isEncrypted());
+ QCOMPARE(socket.state(), QAbstractSocket::UnconnectedState);
+}
+
+void tst_QSslSocket::simpleConnectWithIgnore()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ QSslSocket socket;
+ this->socket = &socket;
+ QSignalSpy encryptedSpy(&socket, SIGNAL(encrypted()));
+ QSignalSpy sslErrorsSpy(&socket, SIGNAL(sslErrors(const QList<QSslError> &)));
+
+ connect(&socket, SIGNAL(readyRead()), this, SLOT(exitLoop()));
+ connect(&socket, SIGNAL(encrypted()), this, SLOT(exitLoop()));
+ connect(&socket, SIGNAL(connected()), this, SLOT(exitLoop()));
+ connect(&socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot()));
+ connect(&socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(exitLoop()));
+
+ // Start connecting
+ socket.connectToHost(QtNetworkSettings::serverName(), 993);
+ QVERIFY(socket.state() != QAbstractSocket::UnconnectedState); // something must be in progress
+ enterLoop(10);
+
+ // Start handshake
+ QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
+ socket.startClientEncryption();
+ enterLoop(10);
+
+ // Done; encryption should be enabled.
+ QCOMPARE(sslErrorsSpy.count(), 1);
+ QVERIFY(socket.isEncrypted());
+ QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
+ QCOMPARE(encryptedSpy.count(), 1);
+
+ // Wait for incoming data
+ if (!socket.canReadLine())
+ enterLoop(10);
+
+ QByteArray data = socket.readAll();
+ socket.disconnectFromHost();
+ QVERIFY2(QtNetworkSettings::compareReplyIMAPSSL(data), data.constData());
+}
+
+void tst_QSslSocket::sslErrors_data()
+{
+ QTest::addColumn<QString>("host");
+ QTest::addColumn<int>("port");
+ QTest::addColumn<SslErrorList>("expected");
+
+ QTest::newRow(qPrintable(QtNetworkSettings::serverLocalName()))
+ << QtNetworkSettings::serverLocalName()
+ << 993
+ << (SslErrorList() << QSslError::HostNameMismatch
+ << QSslError::SelfSignedCertificate);
+}
+
+void tst_QSslSocket::sslErrors()
+{
+ QFETCH(QString, host);
+ QFETCH(int, port);
+ QFETCH(SslErrorList, expected);
+
+ QSslSocketPtr socket = newSocket();
+ socket->connectToHostEncrypted(host, port);
+ if (!socket->waitForConnected())
+ QEXPECT_FAIL("imap.trolltech.com", "server not open to internet", Continue);
+ socket->waitForEncrypted(5000);
+
+ SslErrorList output;
+ foreach (QSslError error, socket->sslErrors()) {
+ output << error.error();
+ }
+
+#ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
+ if (output.count() && output.last() == QSslError::CertificateUntrusted)
+ output.takeLast();
+#endif
+ QCOMPARE(output, expected);
+}
+
+void tst_QSslSocket::addCaCertificate()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+}
+
+void tst_QSslSocket::addCaCertificates()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+}
+
+void tst_QSslSocket::addCaCertificates2()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+}
+
+void tst_QSslSocket::ciphers()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QSslSocket socket;
+ QCOMPARE(socket.ciphers(), QSslSocket::supportedCiphers());
+ socket.setCiphers(QList<QSslCipher>());
+ QVERIFY(socket.ciphers().isEmpty());
+ socket.setCiphers(socket.defaultCiphers());
+ QCOMPARE(socket.ciphers(), QSslSocket::supportedCiphers());
+ socket.setCiphers(socket.defaultCiphers());
+ QCOMPARE(socket.ciphers(), QSslSocket::supportedCiphers());
+
+ // Task 164356
+ socket.setCiphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
+}
+
+void tst_QSslSocket::connectToHostEncrypted()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QSslSocketPtr socket = newSocket();
+ this->socket = socket;
+ QVERIFY(socket->addCaCertificates(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem")));
+#ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
+ connect(socket, SIGNAL(sslErrors(QList<QSslError>)),
+ this, SLOT(untrustedWorkaroundSlot(QList<QSslError>)));
+#endif
+
+ socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+
+ // This should pass unconditionally when using fluke's CA certificate.
+ // or use untrusted certificate workaround
+ QVERIFY2(socket->waitForEncrypted(10000), qPrintable(socket->errorString()));
+
+ socket->disconnectFromHost();
+ QVERIFY(socket->waitForDisconnected());
+
+ QCOMPARE(socket->mode(), QSslSocket::SslClientMode);
+
+ socket->connectToHost(QtNetworkSettings::serverName(), 13);
+
+ QCOMPARE(socket->mode(), QSslSocket::UnencryptedMode);
+
+ QVERIFY(socket->waitForDisconnected());
+}
+
+void tst_QSslSocket::connectToHostEncryptedWithVerificationPeerName()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QSslSocketPtr socket = newSocket();
+ this->socket = socket;
+
+ socket->addCaCertificates(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem"));
+#ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
+ connect(socket, SIGNAL(sslErrors(QList<QSslError>)),
+ this, SLOT(untrustedWorkaroundSlot(QList<QSslError>)));
+#endif
+
+ // connect to the server with its local name, but use the full name for verification.
+ socket->connectToHostEncrypted(QtNetworkSettings::serverLocalName(), 443, QtNetworkSettings::serverName());
+
+ // This should pass unconditionally when using fluke's CA certificate.
+ QVERIFY2(socket->waitForEncrypted(10000), qPrintable(socket->errorString()));
+
+ socket->disconnectFromHost();
+ QVERIFY(socket->waitForDisconnected());
+
+ QCOMPARE(socket->mode(), QSslSocket::SslClientMode);
+}
+
+void tst_QSslSocket::sessionCipher()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QSslSocketPtr socket = newSocket();
+ this->socket = socket;
+ connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
+ QVERIFY(socket->sessionCipher().isNull());
+ socket->connectToHost(QtNetworkSettings::serverName(), 443 /* https */);
+ QVERIFY(socket->waitForConnected(10000));
+ QVERIFY(socket->sessionCipher().isNull());
+ socket->startClientEncryption();
+ QVERIFY(socket->waitForEncrypted(5000));
+ QVERIFY(!socket->sessionCipher().isNull());
+ QVERIFY(QSslSocket::supportedCiphers().contains(socket->sessionCipher()));
+ socket->disconnectFromHost();
+ QVERIFY(socket->waitForDisconnected());
+}
+
+void tst_QSslSocket::flush()
+{
+}
+
+void tst_QSslSocket::isEncrypted()
+{
+}
+
+void tst_QSslSocket::localCertificate()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ // This test does not make 100% sense yet. We just set some local CA/cert/key and use it
+ // to authenticate ourselves against the server. The server does not actually check this
+ // values. This test should just run the codepath inside qsslsocket_openssl.cpp
+
+ QSslSocketPtr socket = newSocket();
+ QList<QSslCertificate> localCert = QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem");
+ socket->setCaCertificates(localCert);
+ socket->setLocalCertificate(QLatin1String(SRCDIR "certs/fluke.cert"));
+ socket->setPrivateKey(QLatin1String(SRCDIR "certs/fluke.key"));
+
+ socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ QVERIFY(socket->waitForEncrypted(10000));
+}
+
+void tst_QSslSocket::mode()
+{
+}
+
+void tst_QSslSocket::peerCertificate()
+{
+}
+
+void tst_QSslSocket::peerCertificateChain()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QSslSocketPtr socket = newSocket();
+ this->socket = socket;
+
+ QList<QSslCertificate> caCertificates = QSslCertificate::fromPath(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem"));
+ QVERIFY(caCertificates.count() == 1);
+ socket->addCaCertificates(caCertificates);
+#ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
+ connect(socket, SIGNAL(sslErrors(QList<QSslError>)),
+ this, SLOT(untrustedWorkaroundSlot(QList<QSslError>)));
+#endif
+
+ socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ QCOMPARE(socket->mode(), QSslSocket::UnencryptedMode);
+ QVERIFY(socket->peerCertificateChain().isEmpty());
+ QVERIFY2(socket->waitForEncrypted(10000), qPrintable(socket->errorString()));
+
+ QList<QSslCertificate> certChain = socket->peerCertificateChain();
+ QVERIFY(certChain.count() > 0);
+ QCOMPARE(certChain.first(), socket->peerCertificate());
+
+ socket->disconnectFromHost();
+ QVERIFY(socket->waitForDisconnected());
+
+ // connect again to a different server
+ socket->connectToHostEncrypted("trolltech.com", 443);
+ socket->ignoreSslErrors();
+ QCOMPARE(socket->mode(), QSslSocket::UnencryptedMode);
+ QVERIFY(socket->peerCertificateChain().isEmpty());
+ QVERIFY2(socket->waitForEncrypted(10000), qPrintable(socket->errorString()));
+
+ QCOMPARE(socket->peerCertificateChain().first(), socket->peerCertificate());
+ QVERIFY(socket->peerCertificateChain() != certChain);
+
+ socket->disconnectFromHost();
+ QVERIFY(socket->waitForDisconnected());
+
+ // now do it again back to the original server
+ socket->connectToHost(QtNetworkSettings::serverName(), 443);
+ QCOMPARE(socket->mode(), QSslSocket::UnencryptedMode);
+ QVERIFY(socket->peerCertificateChain().isEmpty());
+ QVERIFY2(socket->waitForConnected(10000), "Network timeout");
+
+ socket->startClientEncryption();
+ QVERIFY2(socket->waitForEncrypted(10000), qPrintable(socket->errorString()));
+
+ QCOMPARE(socket->peerCertificateChain().first(), socket->peerCertificate());
+ QVERIFY(socket->peerCertificateChain() == certChain);
+
+ socket->disconnectFromHost();
+ QVERIFY(socket->waitForDisconnected());
+}
+
+void tst_QSslSocket::privateKey()
+{
+}
+
+void tst_QSslSocket::privateKeyOpaque()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QFile file(SRCDIR "certs/fluke.key");
+ QVERIFY(file.open(QIODevice::ReadOnly));
+ QSslKey key(file.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
+ QVERIFY(!key.isNull());
+
+ EVP_PKEY *pkey = q_EVP_PKEY_new();
+ q_EVP_PKEY_set1_RSA(pkey, reinterpret_cast<RSA *>(key.handle()));
+
+ // This test does not make 100% sense yet. We just set some local CA/cert/key and use it
+ // to authenticate ourselves against the server. The server does not actually check this
+ // values. This test should just run the codepath inside qsslsocket_openssl.cpp
+
+ QSslSocketPtr socket = newSocket();
+ QList<QSslCertificate> localCert = QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem");
+ socket->setCaCertificates(localCert);
+ socket->setLocalCertificate(QLatin1String(SRCDIR "certs/fluke.cert"));
+ socket->setPrivateKey(QSslKey(reinterpret_cast<Qt::HANDLE>(pkey)));
+
+ socket->setPeerVerifyMode(QSslSocket::QueryPeer);
+ socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ QVERIFY(socket->waitForEncrypted(10000));
+}
+
+void tst_QSslSocket::protocol()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QSslSocketPtr socket = newSocket();
+ this->socket = socket;
+ QList<QSslCertificate> certs = QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem");
+
+ socket->setCaCertificates(certs);
+#ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
+ connect(socket, SIGNAL(sslErrors(QList<QSslError>)),
+ this, SLOT(untrustedWorkaroundSlot(QList<QSslError>)));
+#endif
+
+ QCOMPARE(socket->protocol(), QSsl::SecureProtocols);
+ {
+ // Fluke allows SSLv3.
+ socket->setProtocol(QSsl::SslV3);
+ QCOMPARE(socket->protocol(), QSsl::SslV3);
+ socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString()));
+ QCOMPARE(socket->protocol(), QSsl::SslV3);
+ socket->abort();
+ QCOMPARE(socket->protocol(), QSsl::SslV3);
+ socket->connectToHost(QtNetworkSettings::serverName(), 443);
+ QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
+ socket->startClientEncryption();
+ QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString()));
+ QCOMPARE(socket->protocol(), QSsl::SslV3);
+ socket->abort();
+ }
+ {
+ // Fluke allows TLSV1.
+ socket->setProtocol(QSsl::TlsV1);
+ QCOMPARE(socket->protocol(), QSsl::TlsV1);
+ socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString()));
+ QCOMPARE(socket->protocol(), QSsl::TlsV1);
+ socket->abort();
+ QCOMPARE(socket->protocol(), QSsl::TlsV1);
+ socket->connectToHost(QtNetworkSettings::serverName(), 443);
+ QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
+ socket->startClientEncryption();
+ QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString()));
+ QCOMPARE(socket->protocol(), QSsl::TlsV1);
+ socket->abort();
+ }
+ {
+ // Fluke allows SSLV2.
+ socket->setProtocol(QSsl::SslV2);
+ QCOMPARE(socket->protocol(), QSsl::SslV2);
+ socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ QVERIFY(socket->waitForEncrypted());
+ QCOMPARE(socket->protocol(), QSsl::SslV2);
+ socket->abort();
+ QCOMPARE(socket->protocol(), QSsl::SslV2);
+ socket->connectToHost(QtNetworkSettings::serverName(), 443);
+ QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
+ socket->startClientEncryption();
+ QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString()));
+ socket->abort();
+ }
+ {
+ // Fluke allows SSLV3, so it allows AnyProtocol.
+ socket->setProtocol(QSsl::AnyProtocol);
+ QCOMPARE(socket->protocol(), QSsl::AnyProtocol);
+ socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ QVERIFY(socket->waitForEncrypted());
+ QCOMPARE(socket->protocol(), QSsl::AnyProtocol);
+ socket->abort();
+ QCOMPARE(socket->protocol(), QSsl::AnyProtocol);
+ socket->connectToHost(QtNetworkSettings::serverName(), 443);
+ QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
+ socket->startClientEncryption();
+ QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString()));
+ QCOMPARE(socket->protocol(), QSsl::AnyProtocol);
+ socket->abort();
+ }
+ {
+ // Fluke allows SSLV3, so it allows NoSslV2
+ socket->setProtocol(QSsl::TlsV1SslV3);
+ QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3);
+ socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ QVERIFY(socket->waitForEncrypted());
+ QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3);
+ socket->abort();
+ QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3);
+ socket->connectToHost(QtNetworkSettings::serverName(), 443);
+ QVERIFY2(socket->waitForConnected(), qPrintable(socket->errorString()));
+ socket->startClientEncryption();
+ QVERIFY2(socket->waitForEncrypted(), qPrintable(socket->errorString()));
+ QCOMPARE(socket->protocol(), QSsl::TlsV1SslV3);
+ socket->abort();
+ }
+}
+
+class SslServer : public QTcpServer
+{
+ Q_OBJECT
+public:
+ SslServer(const QString &keyFile = SRCDIR "certs/fluke.key", const QString &certFile = SRCDIR "certs/fluke.cert")
+ : socket(0),
+ protocol(QSsl::TlsV1),
+ m_keyFile(keyFile),
+ m_certFile(certFile) { }
+ QSslSocket *socket;
+ QSsl::SslProtocol protocol;
+ QString m_keyFile;
+ QString m_certFile;
+
+protected:
+ void incomingConnection(int socketDescriptor)
+ {
+ socket = new QSslSocket(this);
+ socket->setProtocol(protocol);
+ connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot()));
+
+ QFile file(m_keyFile);
+ QVERIFY(file.open(QIODevice::ReadOnly));
+ QSslKey key(file.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
+ QVERIFY(!key.isNull());
+ socket->setPrivateKey(key);
+
+ QList<QSslCertificate> localCert = QSslCertificate::fromPath(m_certFile);
+ QVERIFY(!localCert.isEmpty());
+ QVERIFY(localCert.first().handle());
+ socket->setLocalCertificate(localCert.first());
+
+ QVERIFY(socket->setSocketDescriptor(socketDescriptor, QAbstractSocket::ConnectedState));
+ QVERIFY(!socket->peerAddress().isNull());
+ QVERIFY(socket->peerPort() != 0);
+ QVERIFY(!socket->localAddress().isNull());
+ QVERIFY(socket->localPort() != 0);
+
+ socket->startServerEncryption();
+ }
+
+protected slots:
+ void ignoreErrorSlot()
+ {
+ socket->ignoreSslErrors();
+ }
+};
+
+void tst_QSslSocket::protocolServerSide_data()
+{
+
+ QTest::addColumn<QSsl::SslProtocol>("serverProtocol");
+ QTest::addColumn<QSsl::SslProtocol>("clientProtocol");
+ QTest::addColumn<bool>("works");
+
+ QTest::newRow("ssl2-ssl2") << QSsl::SslV2 << QSsl::SslV2 << false; // no idea why it does not work, but we don't care about SSL 2
+ QTest::newRow("ssl3-ssl3") << QSsl::SslV3 << QSsl::SslV3 << true;
+ QTest::newRow("tls1-tls1") << QSsl::TlsV1 << QSsl::TlsV1 << true;
+ QTest::newRow("tls1ssl3-tls1ssl3") << QSsl::TlsV1SslV3 << QSsl::TlsV1SslV3 << true;
+ QTest::newRow("any-any") << QSsl::AnyProtocol << QSsl::AnyProtocol << true;
+ QTest::newRow("secure-secure") << QSsl::SecureProtocols << QSsl::SecureProtocols << true;
+
+ QTest::newRow("ssl2-ssl3") << QSsl::SslV2 << QSsl::SslV3 << false;
+ QTest::newRow("ssl2-tls1") << QSsl::SslV2 << QSsl::TlsV1 << false;
+ QTest::newRow("ssl2-tls1ssl3") << QSsl::SslV2 << QSsl::TlsV1SslV3 << false;
+ QTest::newRow("ssl2-secure") << QSsl::SslV2 << QSsl::SecureProtocols << false;
+ QTest::newRow("ssl2-any") << QSsl::SslV2 << QSsl::AnyProtocol << false; // no idea why it does not work, but we don't care about SSL 2
+
+ QTest::newRow("ssl3-ssl2") << QSsl::SslV3 << QSsl::SslV2 << false;
+ QTest::newRow("ssl3-tls1") << QSsl::SslV3 << QSsl::TlsV1 << false;
+ QTest::newRow("ssl3-tls1ssl3") << QSsl::SslV3 << QSsl::TlsV1SslV3 << true;
+ QTest::newRow("ssl3-secure") << QSsl::SslV3 << QSsl::SecureProtocols << true;
+ QTest::newRow("ssl3-any") << QSsl::SslV3 << QSsl::AnyProtocol << false; // we wont set a SNI header here because we connect to a
+ // numerical IP, so OpenSSL will send a SSL 2 handshake
+
+ QTest::newRow("tls1-ssl2") << QSsl::TlsV1 << QSsl::SslV2 << false;
+ QTest::newRow("tls1-ssl3") << QSsl::TlsV1 << QSsl::SslV3 << false;
+ QTest::newRow("tls1-tls1ssl3") << QSsl::TlsV1 << QSsl::TlsV1SslV3 << true;
+ QTest::newRow("tls1-secure") << QSsl::TlsV1 << QSsl::SecureProtocols << true;
+ QTest::newRow("tls1-any") << QSsl::TlsV1 << QSsl::AnyProtocol << false; // we wont set a SNI header here because we connect to a
+ // numerical IP, so OpenSSL will send a SSL 2 handshake
+
+ QTest::newRow("tls1ssl3-ssl2") << QSsl::TlsV1SslV3 << QSsl::SslV2 << false;
+ QTest::newRow("tls1ssl3-ssl3") << QSsl::TlsV1SslV3 << QSsl::SslV3 << true;
+ QTest::newRow("tls1ssl3-tls1") << QSsl::TlsV1SslV3 << QSsl::TlsV1 << true;
+ QTest::newRow("tls1ssl3-secure") << QSsl::TlsV1SslV3 << QSsl::SecureProtocols << true;
+ QTest::newRow("tls1ssl3-any") << QSsl::TlsV1SslV3 << QSsl::AnyProtocol << true;
+
+ QTest::newRow("secure-ssl2") << QSsl::SecureProtocols << QSsl::SslV2 << false;
+ QTest::newRow("secure-ssl3") << QSsl::SecureProtocols << QSsl::SslV3 << true;
+ QTest::newRow("secure-tls1") << QSsl::SecureProtocols << QSsl::TlsV1 << true;
+ QTest::newRow("secure-tls1ssl3") << QSsl::SecureProtocols << QSsl::TlsV1SslV3 << true;
+ QTest::newRow("secure-any") << QSsl::SecureProtocols << QSsl::AnyProtocol << true;
+
+ QTest::newRow("any-ssl2") << QSsl::AnyProtocol << QSsl::SslV2 << false; // no idea why it does not work, but we don't care about SSL 2
+ QTest::newRow("any-ssl3") << QSsl::AnyProtocol << QSsl::SslV3 << true;
+ QTest::newRow("any-tls1") << QSsl::AnyProtocol << QSsl::TlsV1 << true;
+ QTest::newRow("any-tls1ssl3") << QSsl::AnyProtocol << QSsl::TlsV1SslV3 << true;
+ QTest::newRow("any-secure") << QSsl::AnyProtocol << QSsl::SecureProtocols << true;
+}
+
+void tst_QSslSocket::protocolServerSide()
+{
+ if (!QSslSocket::supportsSsl()) {
+ qWarning("SSL not supported, skipping test");
+ return;
+ }
+
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ QFETCH(QSsl::SslProtocol, serverProtocol);
+ SslServer server;
+ server.protocol = serverProtocol;
+ QVERIFY(server.listen());
+
+ QEventLoop loop;
+ QTimer::singleShot(5000, &loop, SLOT(quit()));
+
+ QSslSocketPtr client = new QSslSocket;
+ socket = client;
+ QFETCH(QSsl::SslProtocol, clientProtocol);
+ socket->setProtocol(clientProtocol);
+ // upon SSL wrong version error, error will be triggered, not sslErrors
+ connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), &loop, SLOT(quit()));
+ connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot()));
+ connect(client, SIGNAL(encrypted()), &loop, SLOT(quit()));
+
+ client->connectToHostEncrypted(QHostAddress(QHostAddress::LocalHost).toString(), server.serverPort());
+
+ loop.exec();
+
+ QFETCH(bool, works);
+ QAbstractSocket::SocketState expectedState = (works) ? QAbstractSocket::ConnectedState : QAbstractSocket::UnconnectedState;
+ QCOMPARE(client->state(), expectedState);
+ QCOMPARE(client->isEncrypted(), works);
+}
+
+void tst_QSslSocket::setCaCertificates()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QSslSocket socket;
+ QCOMPARE(socket.caCertificates(), QSslSocket::defaultCaCertificates());
+ socket.setCaCertificates(QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem"));
+ QCOMPARE(socket.caCertificates().size(), 1);
+ socket.setCaCertificates(socket.defaultCaCertificates());
+ QCOMPARE(socket.caCertificates(), QSslSocket::defaultCaCertificates());
+}
+
+void tst_QSslSocket::setLocalCertificate()
+{
+}
+
+void tst_QSslSocket::setPrivateKey()
+{
+}
+
+void tst_QSslSocket::setSocketDescriptor()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ SslServer server;
+ QVERIFY(server.listen());
+
+ QEventLoop loop;
+ QTimer::singleShot(5000, &loop, SLOT(quit()));
+
+ QSslSocketPtr client = new QSslSocket;
+ socket = client;
+ connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot()));
+ connect(client, SIGNAL(encrypted()), &loop, SLOT(quit()));
+
+ client->connectToHostEncrypted(QHostAddress(QHostAddress::LocalHost).toString(), server.serverPort());
+
+ loop.exec();
+
+ QCOMPARE(client->state(), QAbstractSocket::ConnectedState);
+ QVERIFY(client->isEncrypted());
+ QVERIFY(!client->peerAddress().isNull());
+ QVERIFY(client->peerPort() != 0);
+ QVERIFY(!client->localAddress().isNull());
+ QVERIFY(client->localPort() != 0);
+}
+
+void tst_QSslSocket::setSslConfiguration_data()
+{
+ QTest::addColumn<QSslConfiguration>("configuration");
+ QTest::addColumn<bool>("works");
+
+ QTest::newRow("empty") << QSslConfiguration() << false;
+ QSslConfiguration conf = QSslConfiguration::defaultConfiguration();
+ QTest::newRow("default") << conf << false; // does not contain test server cert
+ QList<QSslCertificate> testServerCert = QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem");
+ conf.setCaCertificates(testServerCert);
+ QTest::newRow("set-root-cert") << conf << true;
+ conf.setProtocol(QSsl::SecureProtocols);
+ QTest::newRow("secure") << conf << true;
+}
+
+void tst_QSslSocket::setSslConfiguration()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QSslSocketPtr socket = newSocket();
+ QFETCH(QSslConfiguration, configuration);
+ socket->setSslConfiguration(configuration);
+ this->socket = socket;
+ socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ QFETCH(bool, works);
+ QCOMPARE(socket->waitForEncrypted(10000), works);
+ if (works) {
+ socket->disconnectFromHost();
+ QVERIFY2(socket->waitForDisconnected(), qPrintable(socket->errorString()));
+ }
+}
+
+void tst_QSslSocket::waitForEncrypted()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QSslSocketPtr socket = newSocket();
+ this->socket = socket;
+
+ connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot()));
+ socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+
+ QVERIFY(socket->waitForEncrypted(10000));
+}
+
+void tst_QSslSocket::waitForEncryptedMinusOne()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QSslSocketPtr socket = newSocket();
+ this->socket = socket;
+
+ connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot()));
+ socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+
+ QVERIFY(socket->waitForEncrypted(-1));
+}
+
+void tst_QSslSocket::waitForConnectedEncryptedReadyRead()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QSslSocketPtr socket = newSocket();
+ this->socket = socket;
+
+ connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot()));
+ socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 993);
+
+#ifdef Q_OS_SYMBIAN
+ QVERIFY(socket->waitForConnected(10000));
+ QVERIFY(socket->waitForEncrypted(10000));
+
+ // dont forget to login
+ QCOMPARE((int) socket->write("USER ftptest\r\n"), 14);
+ QCOMPARE((int) socket->write("PASS ftP2Ptf\r\n"), 14);
+
+ QVERIFY(socket->waitForReadyRead(10000));
+ QVERIFY(!socket->peerCertificate().isNull());
+ QVERIFY(!socket->peerCertificateChain().isEmpty());
+#else
+ QVERIFY(socket->waitForConnected(10000));
+ QVERIFY(socket->waitForEncrypted(10000));
+ QVERIFY(socket->waitForReadyRead(10000));
+ QVERIFY(!socket->peerCertificate().isNull());
+ QVERIFY(!socket->peerCertificateChain().isEmpty());
+#endif
+}
+
+void tst_QSslSocket::startClientEncryption()
+{
+}
+
+void tst_QSslSocket::startServerEncryption()
+{
+}
+
+void tst_QSslSocket::addDefaultCaCertificate()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ // Reset the global CA chain
+ QSslSocket::setDefaultCaCertificates(QSslSocket::systemCaCertificates());
+
+ QList<QSslCertificate> flukeCerts = QSslCertificate::fromPath(SRCDIR "certs/qt-test-server-cacert.pem");
+ QCOMPARE(flukeCerts.size(), 1);
+ QList<QSslCertificate> globalCerts = QSslSocket::defaultCaCertificates();
+ QVERIFY(!globalCerts.contains(flukeCerts.first()));
+ QSslSocket::addDefaultCaCertificate(flukeCerts.first());
+ QCOMPARE(QSslSocket::defaultCaCertificates().size(), globalCerts.size() + 1);
+ QVERIFY(QSslSocket::defaultCaCertificates().contains(flukeCerts.first()));
+
+ // Restore the global CA chain
+ QSslSocket::setDefaultCaCertificates(QSslSocket::systemCaCertificates());
+}
+
+void tst_QSslSocket::addDefaultCaCertificates()
+{
+}
+
+void tst_QSslSocket::addDefaultCaCertificates2()
+{
+}
+
+void tst_QSslSocket::defaultCaCertificates()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QList<QSslCertificate> certs = QSslSocket::defaultCaCertificates();
+ QVERIFY(certs.size() > 1);
+ QCOMPARE(certs, QSslSocket::systemCaCertificates());
+}
+
+void tst_QSslSocket::defaultCiphers()
+{
+}
+
+void tst_QSslSocket::resetDefaultCiphers()
+{
+}
+
+void tst_QSslSocket::setDefaultCaCertificates()
+{
+}
+
+void tst_QSslSocket::setDefaultCiphers()
+{
+}
+
+void tst_QSslSocket::supportedCiphers()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QList<QSslCipher> ciphers = QSslSocket::supportedCiphers();
+ QVERIFY(ciphers.size() > 1);
+
+ QSslSocket socket;
+ QCOMPARE(socket.supportedCiphers(), ciphers);
+ QCOMPARE(socket.defaultCiphers(), ciphers);
+ QCOMPARE(socket.ciphers(), ciphers);
+}
+
+void tst_QSslSocket::systemCaCertificates()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QList<QSslCertificate> certs = QSslSocket::systemCaCertificates();
+ QVERIFY(certs.size() > 1);
+ QCOMPARE(certs, QSslSocket::defaultCaCertificates());
+}
+
+void tst_QSslSocket::wildcardCertificateNames()
+{
+ // Passing CN matches
+ QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("www.example.com"), QString("www.example.com")), true );
+ QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*.example.com"), QString("www.example.com")), true );
+ QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("xxx*.example.com"), QString("xxxwww.example.com")), true );
+ QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("f*.example.com"), QString("foo.example.com")), true );
+ QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("192.168.0.0"), QString("192.168.0.0")), true );
+
+ // Failing CN matches
+ QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("xxx.example.com"), QString("www.example.com")), false );
+ QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*"), QString("www.example.com")), false );
+ QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*.*.com"), QString("www.example.com")), false );
+ QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*.example.com"), QString("baa.foo.example.com")), false );
+ QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("f*.example.com"), QString("baa.example.com")), false );
+ QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*.com"), QString("example.com")), false );
+ QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*fail.com"), QString("example.com")), false );
+ QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*.example."), QString("www.example.")), false );
+ QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*.example."), QString("www.example")), false );
+ QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString(""), QString("www")), false );
+ QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*"), QString("www")), false );
+ QCOMPARE( QSslSocketBackendPrivate::isMatchingHostname(QString("*.168.0.0"), QString("192.168.0.0")), false );
+}
+
+void tst_QSslSocket::wildcard()
+{
+ QSKIP("TODO: solve wildcard problem", SkipAll);
+
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ // Fluke runs an apache server listening on port 4443, serving the
+ // wildcard fluke.*.troll.no. The DNS entry for
+ // fluke.wildcard.dev.troll.no, served by ares (root for dev.troll.no),
+ // returns the CNAME fluke.troll.no for this domain. The web server
+ // responds with the wildcard, and QSslSocket should accept that as a
+ // valid connection. This was broken in 4.3.0.
+ QSslSocketPtr socket = newSocket();
+ socket->addCaCertificates(QLatin1String("certs/aspiriniks.ca.crt"));
+ this->socket = socket;
+#ifdef QSSLSOCKET_CERTUNTRUSTED_WORKAROUND
+ connect(socket, SIGNAL(sslErrors(QList<QSslError>)),
+ this, SLOT(untrustedWorkaroundSlot(QList<QSslError>)));
+#endif
+ socket->connectToHostEncrypted(QtNetworkSettings::wildcardServerName(), 4443);
+
+ QVERIFY2(socket->waitForEncrypted(3000), qPrintable(socket->errorString()));
+
+ QSslCertificate certificate = socket->peerCertificate();
+ QCOMPARE(certificate.subjectInfo(QSslCertificate::CommonName), QString(QtNetworkSettings::serverLocalName() + ".*." + QtNetworkSettings::serverDomainName()));
+ QCOMPARE(certificate.issuerInfo(QSslCertificate::CommonName), QtNetworkSettings::serverName());
+
+ socket->close();
+}
+
+class SslServer2 : public QTcpServer
+{
+protected:
+ void incomingConnection(int socketDescriptor)
+ {
+ QSslSocket *socket = new QSslSocket(this);
+ socket->ignoreSslErrors();
+
+ // Only set the certificate
+ QList<QSslCertificate> localCert = QSslCertificate::fromPath(SRCDIR "certs/fluke.cert");
+ QVERIFY(!localCert.isEmpty());
+ QVERIFY(localCert.first().handle());
+ socket->setLocalCertificate(localCert.first());
+
+ QVERIFY(socket->setSocketDescriptor(socketDescriptor, QAbstractSocket::ConnectedState));
+
+ socket->startServerEncryption();
+ }
+};
+
+void tst_QSslSocket::setEmptyKey()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ SslServer2 server;
+ server.listen();
+
+ QSslSocket socket;
+ socket.connectToHostEncrypted("127.0.0.1", server.serverPort());
+
+ QTestEventLoop::instance().enterLoop(2);
+
+ QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
+ QCOMPARE(socket.error(), QAbstractSocket::UnknownSocketError);
+}
+
+void tst_QSslSocket::spontaneousWrite()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ SslServer server;
+ QSslSocket *receiver = new QSslSocket(this);
+ connect(receiver, SIGNAL(readyRead()), SLOT(exitLoop()));
+
+ // connect two sockets to each other:
+ QVERIFY(server.listen(QHostAddress::LocalHost));
+ receiver->connectToHost("127.0.0.1", server.serverPort());
+ QVERIFY(receiver->waitForConnected(5000));
+ QVERIFY(server.waitForNewConnection(0));
+
+ QSslSocket *sender = server.socket;
+ QVERIFY(sender);
+ QVERIFY(sender->state() == QAbstractSocket::ConnectedState);
+ receiver->setObjectName("receiver");
+ sender->setObjectName("sender");
+ receiver->ignoreSslErrors();
+ receiver->startClientEncryption();
+
+ // SSL handshake:
+ connect(receiver, SIGNAL(encrypted()), SLOT(exitLoop()));
+ enterLoop(1);
+ QVERIFY(!timeout());
+ QVERIFY(sender->isEncrypted());
+ QVERIFY(receiver->isEncrypted());
+
+ // make sure there's nothing to be received on the sender:
+ while (sender->waitForReadyRead(10) || receiver->waitForBytesWritten(10)) {}
+
+ // spontaneously write something:
+ QByteArray data("Hello World");
+ sender->write(data);
+
+ // check if the other side receives it:
+ enterLoop(1);
+ QVERIFY(!timeout());
+ QCOMPARE(receiver->bytesAvailable(), qint64(data.size()));
+ QCOMPARE(receiver->readAll(), data);
+}
+
+void tst_QSslSocket::setReadBufferSize()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ SslServer server;
+ QSslSocket *receiver = new QSslSocket(this);
+ connect(receiver, SIGNAL(readyRead()), SLOT(exitLoop()));
+
+ // connect two sockets to each other:
+ QVERIFY(server.listen(QHostAddress::LocalHost));
+ receiver->connectToHost("127.0.0.1", server.serverPort());
+ QVERIFY(receiver->waitForConnected(5000));
+ QVERIFY(server.waitForNewConnection(0));
+
+ QSslSocket *sender = server.socket;
+ QVERIFY(sender);
+ QVERIFY(sender->state() == QAbstractSocket::ConnectedState);
+ receiver->setObjectName("receiver");
+ sender->setObjectName("sender");
+ receiver->ignoreSslErrors();
+ receiver->startClientEncryption();
+
+ // SSL handshake:
+ connect(receiver, SIGNAL(encrypted()), SLOT(exitLoop()));
+ enterLoop(1);
+ QVERIFY(!timeout());
+ QVERIFY(sender->isEncrypted());
+ QVERIFY(receiver->isEncrypted());
+
+ QByteArray data(2048, 'b');
+ receiver->setReadBufferSize(39 * 1024); // make it a non-multiple of the data.size()
+
+ // saturate the incoming buffer
+ while (sender->state() == QAbstractSocket::ConnectedState &&
+ receiver->state() == QAbstractSocket::ConnectedState &&
+ receiver->bytesAvailable() < receiver->readBufferSize()) {
+ sender->write(data);
+ //qDebug() << receiver->bytesAvailable() << "<" << receiver->readBufferSize() << (receiver->bytesAvailable() < receiver->readBufferSize());
+
+ while (sender->bytesToWrite())
+ QVERIFY(sender->waitForBytesWritten(10));
+
+ // drain it:
+ while (receiver->bytesAvailable() < receiver->readBufferSize() &&
+ receiver->waitForReadyRead(10)) {}
+ }
+
+ //qDebug() << sender->bytesToWrite() << "bytes to write";
+ //qDebug() << receiver->bytesAvailable() << "bytes available";
+
+ // send a bit more
+ sender->write(data);
+ sender->write(data);
+ sender->write(data);
+ sender->write(data);
+ QVERIFY(sender->waitForBytesWritten(10));
+
+ qint64 oldBytesAvailable = receiver->bytesAvailable();
+
+ // now unset the read buffer limit and iterate
+ receiver->setReadBufferSize(0);
+ enterLoop(1);
+ QVERIFY(!timeout());
+
+ QVERIFY(receiver->bytesAvailable() > oldBytesAvailable);
+}
+
+class SetReadBufferSize_task_250027_handler : public QObject {
+ Q_OBJECT
+public slots:
+ void readyReadSlot() {
+ QTestEventLoop::instance().exitLoop();
+ }
+ void waitSomeMore(QSslSocket *socket) {
+ QTime t;
+ t.start();
+ while (!socket->encryptedBytesAvailable()) {
+ QCoreApplication::processEvents(QEventLoop::AllEvents | QEventLoop::WaitForMoreEvents, 250);
+ if (t.elapsed() > 1000 || socket->state() != QAbstractSocket::ConnectedState)
+ return;
+ }
+ }
+};
+
+void tst_QSslSocket::setReadBufferSize_task_250027()
+{
+ // do not execute this when a proxy is set.
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ QSslSocketPtr socket = newSocket();
+ socket->setReadBufferSize(1000); // limit to 1 kb/sec
+ socket->ignoreSslErrors();
+ socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->ignoreSslErrors();
+ QVERIFY(socket->waitForConnected(10*1000));
+ QVERIFY(socket->waitForEncrypted(10*1000));
+
+ // exit the event loop as soon as we receive a readyRead()
+ SetReadBufferSize_task_250027_handler setReadBufferSize_task_250027_handler;
+ connect(socket, SIGNAL(readyRead()), &setReadBufferSize_task_250027_handler, SLOT(readyReadSlot()));
+
+ // provoke a response by sending a request
+ socket->write("GET /qtest/fluke.gif HTTP/1.0\n"); // this file is 27 KB
+ socket->write("Host: ");
+ socket->write(QtNetworkSettings::serverName().toLocal8Bit().constData());
+ socket->write("\n");
+ socket->write("Connection: close\n");
+ socket->write("\n");
+ socket->flush();
+
+ QTestEventLoop::instance().enterLoop(10);
+ setReadBufferSize_task_250027_handler.waitSomeMore(socket);
+ QByteArray firstRead = socket->readAll();
+ // First read should be some data, but not the whole file
+ QVERIFY(firstRead.size() > 0 && firstRead.size() < 20*1024);
+
+ QTestEventLoop::instance().enterLoop(10);
+ setReadBufferSize_task_250027_handler.waitSomeMore(socket);
+ QByteArray secondRead = socket->readAll();
+ // second read should be some more data
+ QVERIFY(secondRead.size() > 0);
+
+ socket->close();
+}
+
+class SslServer3 : public QTcpServer
+{
+ Q_OBJECT
+public:
+ SslServer3() : socket(0) { }
+ QSslSocket *socket;
+
+protected:
+ void incomingConnection(int socketDescriptor)
+ {
+ socket = new QSslSocket(this);
+ connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot()));
+
+ QFile file(SRCDIR "certs/fluke.key");
+ QVERIFY(file.open(QIODevice::ReadOnly));
+ QSslKey key(file.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey);
+ QVERIFY(!key.isNull());
+ socket->setPrivateKey(key);
+
+ QList<QSslCertificate> localCert = QSslCertificate::fromPath(SRCDIR "certs/fluke.cert");
+ QVERIFY(!localCert.isEmpty());
+ QVERIFY(localCert.first().handle());
+ socket->setLocalCertificate(localCert.first());
+
+ QVERIFY(socket->setSocketDescriptor(socketDescriptor, QAbstractSocket::ConnectedState));
+ QVERIFY(!socket->peerAddress().isNull());
+ QVERIFY(socket->peerPort() != 0);
+ QVERIFY(!socket->localAddress().isNull());
+ QVERIFY(socket->localPort() != 0);
+ }
+
+protected slots:
+ void ignoreErrorSlot()
+ {
+ socket->ignoreSslErrors();
+ }
+};
+
+class ThreadedSslServer: public QThread
+{
+ Q_OBJECT
+public:
+ QSemaphore dataReadSemaphore;
+ int serverPort;
+ bool ok;
+
+ ThreadedSslServer() : serverPort(-1), ok(false)
+ { }
+
+ ~ThreadedSslServer()
+ {
+ if (isRunning()) wait(2000);
+ QVERIFY(ok);
+ }
+
+signals:
+ void listening();
+
+protected:
+ void run()
+ {
+ // if all goes well (no timeouts), this thread will sleep for a total of 500 ms
+ // (i.e., 5 times 100 ms, one sleep for each operation)
+
+ SslServer3 server;
+ server.listen(QHostAddress::LocalHost);
+ serverPort = server.serverPort();
+ emit listening();
+
+ // delayed acceptance:
+ QTest::qSleep(100);
+#ifndef Q_OS_SYMBIAN
+ bool ret = server.waitForNewConnection(2000);
+#else
+ bool ret = server.waitForNewConnection(20000);
+#endif
+ Q_UNUSED(ret);
+
+ // delayed start of encryption
+ QTest::qSleep(100);
+ QSslSocket *socket = server.socket;
+ if (!socket || !socket->isValid())
+ return; // error
+ socket->ignoreSslErrors();
+ socket->startServerEncryption();
+ if (!socket->waitForEncrypted(2000))
+ return; // error
+
+ // delayed reading data
+ QTest::qSleep(100);
+ if (!socket->waitForReadyRead(2000))
+ return; // error
+ socket->readAll();
+ dataReadSemaphore.release();
+
+ // delayed sending data
+ QTest::qSleep(100);
+ socket->write("Hello, World");
+ while (socket->bytesToWrite())
+ if (!socket->waitForBytesWritten(2000))
+ return; // error
+
+ // delayed replying (reading then sending)
+ QTest::qSleep(100);
+ if (!socket->waitForReadyRead(2000))
+ return; // error
+ socket->write("Hello, World");
+ while (socket->bytesToWrite())
+ if (!socket->waitForBytesWritten(2000))
+ return; // error
+
+ // delayed disconnection:
+ QTest::qSleep(100);
+ socket->disconnectFromHost();
+ if (!socket->waitForDisconnected(2000))
+ return; // error
+
+ delete socket;
+ ok = true;
+ }
+};
+
+void tst_QSslSocket::waitForMinusOne()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ ThreadedSslServer server;
+ connect(&server, SIGNAL(listening()), SLOT(exitLoop()));
+
+ // start the thread and wait for it to be ready
+ server.start();
+ enterLoop(1);
+ QVERIFY(!timeout());
+
+ // connect to the server
+ QSslSocket socket;
+ QTest::qSleep(100);
+ socket.connectToHost("127.0.0.1", server.serverPort);
+ QVERIFY(socket.waitForConnected(-1));
+ socket.ignoreSslErrors();
+ socket.startClientEncryption();
+
+ // first verification: this waiting should take 200 ms
+ QVERIFY2(socket.waitForEncrypted(-1), qPrintable(socket.errorString()));
+ QVERIFY(socket.isEncrypted());
+ QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
+ QCOMPARE(socket.bytesAvailable(), Q_INT64_C(0));
+
+ // second verification: write and make sure the other side got it (100 ms)
+ socket.write("How are you doing?");
+ QVERIFY(socket.bytesToWrite() != 0);
+ QVERIFY(socket.waitForBytesWritten(-1));
+ QVERIFY(server.dataReadSemaphore.tryAcquire(1, 2000));
+
+ // third verification: it should wait for 100 ms:
+ QVERIFY(socket.waitForReadyRead(-1));
+ QVERIFY(socket.isEncrypted());
+ QCOMPARE(socket.state(), QAbstractSocket::ConnectedState);
+ QVERIFY(socket.bytesAvailable() != 0);
+
+ // fourth verification: deadlock prevention:
+ // we write and then wait for reading; the other side needs to receive before
+ // replying (100 ms delay)
+ socket.write("I'm doing just fine!");
+ QVERIFY(socket.bytesToWrite() != 0);
+ QVERIFY(socket.waitForReadyRead(-1));
+
+ // fifth verification: it should wait for 200 ms more
+ QVERIFY(socket.waitForDisconnected(-1));
+}
+
+class VerifyServer : public QTcpServer
+{
+ Q_OBJECT
+public:
+ VerifyServer() : socket(0) { }
+ QSslSocket *socket;
+
+protected:
+ void incomingConnection(int socketDescriptor)
+ {
+ socket = new QSslSocket(this);
+
+ socket->setPrivateKey(SRCDIR "certs/fluke.key");
+ socket->setLocalCertificate(SRCDIR "certs/fluke.cert");
+ socket->setSocketDescriptor(socketDescriptor);
+ socket->startServerEncryption();
+ }
+};
+
+void tst_QSslSocket::verifyMode()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ QSslSocket socket;
+ QCOMPARE(socket.peerVerifyMode(), QSslSocket::AutoVerifyPeer);
+ socket.setPeerVerifyMode(QSslSocket::VerifyNone);
+ QCOMPARE(socket.peerVerifyMode(), QSslSocket::VerifyNone);
+ socket.setPeerVerifyMode(QSslSocket::VerifyNone);
+ socket.setPeerVerifyMode(QSslSocket::VerifyPeer);
+ QCOMPARE(socket.peerVerifyMode(), QSslSocket::VerifyPeer);
+
+ socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ QVERIFY(!socket.waitForEncrypted());
+
+ QList<QSslError> expectedErrors = QList<QSslError>()
+ << QSslError(QSslError::SelfSignedCertificate, socket.peerCertificate());
+ QCOMPARE(socket.sslErrors(), expectedErrors);
+ socket.abort();
+
+ VerifyServer server;
+ server.listen();
+
+ QSslSocket clientSocket;
+ clientSocket.connectToHostEncrypted("127.0.0.1", server.serverPort());
+ clientSocket.ignoreSslErrors();
+
+ QEventLoop loop;
+ QTimer::singleShot(5000, &loop, SLOT(quit()));
+ connect(&clientSocket, SIGNAL(encrypted()), &loop, SLOT(quit()));
+ loop.exec();
+
+ QVERIFY(clientSocket.isEncrypted());
+ QVERIFY(server.socket->sslErrors().isEmpty());
+}
+
+void tst_QSslSocket::verifyDepth()
+{
+ QSslSocket socket;
+ QCOMPARE(socket.peerVerifyDepth(), 0);
+ socket.setPeerVerifyDepth(1);
+ QCOMPARE(socket.peerVerifyDepth(), 1);
+ QTest::ignoreMessage(QtWarningMsg, "QSslSocket::setPeerVerifyDepth: cannot set negative depth of -1");
+ socket.setPeerVerifyDepth(-1);
+ QCOMPARE(socket.peerVerifyDepth(), 1);
+}
+
+void tst_QSslSocket::peerVerifyError()
+{
+ QSslSocketPtr socket = newSocket();
+ QSignalSpy sslErrorsSpy(socket, SIGNAL(sslErrors(QList<QSslError>)));
+ QSignalSpy peerVerifyErrorSpy(socket, SIGNAL(peerVerifyError(QSslError)));
+
+ socket->connectToHostEncrypted(QHostInfo::fromName(QtNetworkSettings::serverName()).addresses().first().toString(), 443);
+ QVERIFY(!socket->waitForEncrypted(10000));
+ QVERIFY(!peerVerifyErrorSpy.isEmpty());
+ QVERIFY(!sslErrorsSpy.isEmpty());
+ QCOMPARE(qVariantValue<QSslError>(peerVerifyErrorSpy.last().at(0)).error(), QSslError::HostNameMismatch);
+ QCOMPARE(qVariantValue<QList<QSslError> >(sslErrorsSpy.at(0).at(0)).size(), peerVerifyErrorSpy.size());
+}
+
+void tst_QSslSocket::disconnectFromHostWhenConnecting()
+{
+ QSslSocketPtr socket = newSocket();
+ socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 993);
+ socket->ignoreSslErrors();
+ socket->write("XXXX LOGOUT\r\n");
+ QAbstractSocket::SocketState state = socket->state();
+ // without proxy, the state will be HostLookupState;
+ // with proxy, the state will be ConnectingState.
+ QVERIFY(socket->state() == QAbstractSocket::HostLookupState ||
+ socket->state() == QAbstractSocket::ConnectingState);
+ socket->disconnectFromHost();
+ // the state of the socket must be the same before and after calling
+ // disconnectFromHost()
+ QCOMPARE(state, socket->state());
+ QVERIFY(socket->state() == QAbstractSocket::HostLookupState ||
+ socket->state() == QAbstractSocket::ConnectingState);
+ QVERIFY(socket->waitForDisconnected(10000));
+ QCOMPARE(socket->state(), QAbstractSocket::UnconnectedState);
+ // we did not call close, so the socket must be still open
+ QVERIFY(socket->isOpen());
+ QCOMPARE(socket->bytesToWrite(), qint64(0));
+
+ // dont forget to login
+ QCOMPARE((int) socket->write("USER ftptest\r\n"), 14);
+
+}
+
+void tst_QSslSocket::disconnectFromHostWhenConnected()
+{
+ QSslSocketPtr socket = newSocket();
+ socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 993);
+ socket->ignoreSslErrors();
+#ifndef Q_OS_SYMBIAN
+ QVERIFY(socket->waitForEncrypted(5000));
+#else
+ QVERIFY(socket->waitForEncrypted(10000));
+#endif
+ socket->write("XXXX LOGOUT\r\n");
+ QCOMPARE(socket->state(), QAbstractSocket::ConnectedState);
+ socket->disconnectFromHost();
+ QCOMPARE(socket->state(), QAbstractSocket::ClosingState);
+#ifdef Q_OS_SYMBIAN
+ // I don't understand how socket->waitForDisconnected can work on other platforms
+ // since socket->write will end to:
+ // QMetaObject::invokeMethod(this, "_q_flushWriteBuffer", Qt::QueuedConnection);
+ // In order that _q_flushWriteBuffer will be called the eventloop need to run
+ // If we just call waitForDisconnected, which blocks the whole thread how that can happen?
+ connect(socket, SIGNAL(disconnected()), this, SLOT(exitLoop()));
+ enterLoop(5);
+ QVERIFY(!timeout());
+#else
+ QVERIFY(socket->waitForDisconnected(5000));
+#endif
+ QCOMPARE(socket->bytesToWrite(), qint64(0));
+}
+
+void tst_QSslSocket::resetProxy()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ // check fix for bug 199941
+
+ QNetworkProxy goodProxy(QNetworkProxy::NoProxy);
+ QNetworkProxy badProxy(QNetworkProxy::HttpProxy, "thisCannotWorkAbsolutelyNotForSure", 333);
+
+ // make sure the connection works, and then set a nonsense proxy, and then
+ // make sure it does not work anymore
+ QSslSocket socket;
+ socket.addCaCertificates(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem"));
+ socket.setProxy(goodProxy);
+ socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ QVERIFY2(socket.waitForConnected(10000), qPrintable(socket.errorString()));
+ socket.abort();
+ socket.setProxy(badProxy);
+ socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ QVERIFY(! socket.waitForConnected(10000));
+
+ // dont forget to login
+ QCOMPARE((int) socket.write("USER ftptest\r\n"), 14);
+ QCOMPARE((int) socket.write("PASS password\r\n"), 15);
+
+ enterLoop(10);
+
+ // now the other way round:
+ // set the nonsense proxy and make sure the connection does not work,
+ // and then set the right proxy and make sure it works
+ QSslSocket socket2;
+ socket2.addCaCertificates(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem"));
+ socket2.setProxy(badProxy);
+ socket2.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ QVERIFY(! socket2.waitForConnected(10000));
+ socket2.abort();
+ socket2.setProxy(goodProxy);
+ socket2.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ QVERIFY2(socket2.waitForConnected(10000), qPrintable(socket.errorString()));
+}
+
+void tst_QSslSocket::ignoreSslErrorsList_data()
+{
+ QTest::addColumn<QList<QSslError> >("expectedSslErrors");
+ QTest::addColumn<int>("expectedSslErrorSignalCount");
+
+ // construct the list of errors that we will get with the SSL handshake and that we will ignore
+ QList<QSslError> expectedSslErrors;
+ // fromPath gives us a list of certs, but it actually only contains one
+ QList<QSslCertificate> certs = QSslCertificate::fromPath(QLatin1String(SRCDIR "certs/qt-test-server-cacert.pem"));
+ QSslError rightError(QSslError::SelfSignedCertificate, certs.at(0));
+ QSslError wrongError(QSslError::SelfSignedCertificate);
+
+
+ QTest::newRow("SSL-failure-empty-list") << expectedSslErrors << 1;
+ expectedSslErrors.append(wrongError);
+ QTest::newRow("SSL-failure-wrong-error") << expectedSslErrors << 1;
+ expectedSslErrors.append(rightError);
+ QTest::newRow("allErrorsInExpectedList1") << expectedSslErrors << 0;
+ expectedSslErrors.removeAll(wrongError);
+ QTest::newRow("allErrorsInExpectedList2") << expectedSslErrors << 0;
+ expectedSslErrors.removeAll(rightError);
+ QTest::newRow("SSL-failure-empty-list-again") << expectedSslErrors << 1;
+}
+
+void tst_QSslSocket::ignoreSslErrorsList()
+{
+ QSslSocket socket;
+ connect(&socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
+ this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
+
+// this->socket = &socket;
+ QSslCertificate cert;
+
+ QFETCH(QList<QSslError>, expectedSslErrors);
+ socket.ignoreSslErrors(expectedSslErrors);
+
+ QFETCH(int, expectedSslErrorSignalCount);
+ QSignalSpy sslErrorsSpy(&socket, SIGNAL(error(QAbstractSocket::SocketError)));
+
+ socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+
+ bool expectEncryptionSuccess = (expectedSslErrorSignalCount == 0);
+ QCOMPARE(socket.waitForEncrypted(10000), expectEncryptionSuccess);
+ QCOMPARE(sslErrorsSpy.count(), expectedSslErrorSignalCount);
+}
+
+void tst_QSslSocket::ignoreSslErrorsListWithSlot_data()
+{
+ ignoreSslErrorsList_data();
+}
+
+// this is not a test, just a slot called in the test below
+void tst_QSslSocket::ignoreErrorListSlot(const QList<QSslError> &)
+{
+ socket->ignoreSslErrors(storedExpectedSslErrors);
+}
+
+void tst_QSslSocket::ignoreSslErrorsListWithSlot()
+{
+ QSslSocket socket;
+ this->socket = &socket;
+
+ QFETCH(QList<QSslError>, expectedSslErrors);
+ // store the errors to ignore them later in the slot connected below
+ storedExpectedSslErrors = expectedSslErrors;
+ connect(&socket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
+ this, SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
+ connect(&socket, SIGNAL(sslErrors(const QList<QSslError> &)),
+ this, SLOT(ignoreErrorListSlot(const QList<QSslError> &)));
+ socket.connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+
+ QFETCH(int, expectedSslErrorSignalCount);
+ bool expectEncryptionSuccess = (expectedSslErrorSignalCount == 0);
+ QCOMPARE(socket.waitForEncrypted(10000), expectEncryptionSuccess);
+}
+
+// make sure a closed socket has no bytesAvailable()
+// related to https://bugs.webkit.org/show_bug.cgi?id=28016
+void tst_QSslSocket::readFromClosedSocket()
+{
+ QSslSocketPtr socket = newSocket();
+ socket->ignoreSslErrors();
+ socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ socket->ignoreSslErrors();
+ socket->waitForConnected();
+ socket->waitForEncrypted();
+ // provoke a response by sending a request
+ socket->write("GET /qtest/fluke.gif HTTP/1.1\n");
+ socket->write("Host: ");
+ socket->write(QtNetworkSettings::serverName().toLocal8Bit().constData());
+ socket->write("\n");
+ socket->write("\n");
+ socket->waitForBytesWritten();
+ socket->waitForReadyRead();
+ QVERIFY(socket->state() == QAbstractSocket::ConnectedState);
+ QVERIFY(socket->bytesAvailable());
+ socket->close();
+ QVERIFY(!socket->bytesAvailable());
+ QVERIFY(!socket->bytesToWrite());
+ QVERIFY(socket->state() == QAbstractSocket::UnconnectedState);
+}
+
+void tst_QSslSocket::writeBigChunk()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QSslSocketPtr socket = newSocket();
+ this->socket = socket;
+
+ connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot()));
+ socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+
+ QByteArray data;
+ data.resize(1024*1024*10); // 10 MB
+ // init with garbage. needed so ssl cannot compress it in an efficient way.
+ for (size_t i = 0; i < data.size() / sizeof(int); i++) {
+ int r = qrand();
+ data.data()[i*sizeof(int)] = r;
+ }
+
+ QVERIFY(socket->waitForEncrypted(10000));
+ QString errorBefore = socket->errorString();
+
+ int ret = socket->write(data.constData(), data.size());
+ QVERIFY(data.size() == ret);
+
+ // spin the event loop once so QSslSocket::transmit() gets called
+ QCoreApplication::processEvents();
+ QString errorAfter = socket->errorString();
+
+ // no better way to do this right now since the error is the same as the default error.
+ if (socket->errorString().startsWith(QLatin1String("Unable to write data")))
+ {
+ qWarning() << socket->error() << socket->errorString();
+ QFAIL("Error while writing! Check if the OpenSSL BIO size is limited?!");
+ }
+ // also check the error string. If another error (than UnknownError) occurred, it should be different than before
+ QVERIFY(errorBefore == errorAfter);
+
+ // check that everything has been written to OpenSSL
+ QVERIFY(socket->bytesToWrite() == 0);
+
+ socket->close();
+}
+
+void tst_QSslSocket::blacklistedCertificates()
+{
+ QFETCH_GLOBAL(bool, setProxy);
+ if (setProxy)
+ return;
+
+ SslServer server(SRCDIR "certs/fake-login.live.com.key", SRCDIR "certs/fake-login.live.com.pem");
+ QSslSocket *receiver = new QSslSocket(this);
+ connect(receiver, SIGNAL(readyRead()), SLOT(exitLoop()));
+
+ // connect two sockets to each other:
+ QVERIFY(server.listen(QHostAddress::LocalHost));
+ receiver->connectToHost("127.0.0.1", server.serverPort());
+ QVERIFY(receiver->waitForConnected(5000));
+ QVERIFY(server.waitForNewConnection(0));
+
+ QSslSocket *sender = server.socket;
+ QVERIFY(sender);
+ QVERIFY(sender->state() == QAbstractSocket::ConnectedState);
+ receiver->setObjectName("receiver");
+ sender->setObjectName("sender");
+ receiver->startClientEncryption();
+
+ connect(receiver, SIGNAL(sslErrors(QList<QSslError>)), SLOT(exitLoop()));
+ connect(receiver, SIGNAL(encrypted()), SLOT(exitLoop()));
+ enterLoop(1);
+ QList<QSslError> sslErrors = receiver->sslErrors();
+ QVERIFY(sslErrors.count() > 0);
+ // there are more errors (self signed cert and hostname mismatch), but we only care about the blacklist error
+ QCOMPARE(sslErrors.at(0).error(), QSslError::CertificateBlacklisted);
+}
+
+void tst_QSslSocket::setEmptyDefaultConfiguration()
+{
+ // used to produce a crash in QSslConfigurationPrivate::deepCopyDefaultConfiguration, QTBUG-13265
+
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ QSslConfiguration emptyConf;
+ QSslConfiguration::setDefaultConfiguration(emptyConf);
+
+ QSslSocketPtr socket = newSocket();
+ connect(socket, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(ignoreErrorSlot()));
+ socket->connectToHostEncrypted(QtNetworkSettings::serverName(), 443);
+ QVERIFY2(!socket->waitForEncrypted(4000), qPrintable(socket->errorString()));
+}
+
+void tst_QSslSocket::versionAccessors()
+{
+ if (!QSslSocket::supportsSsl())
+ return;
+
+ qDebug() << QSslSocket::sslLibraryVersionString();
+ qDebug() << QString::number(QSslSocket::sslLibraryVersionNumber(), 16);
+}
+
+#endif // QT_NO_OPENSSL
+
+QTEST_MAIN(tst_QSslSocket)
+#include "tst_qsslsocket.moc"
diff --git a/tests/auto/network/ssl/ssl.pro b/tests/auto/network/ssl/ssl.pro
new file mode 100644
index 0000000000..fd57a1729b
--- /dev/null
+++ b/tests/auto/network/ssl/ssl.pro
@@ -0,0 +1,8 @@
+TEMPLATE=subdirs
+SUBDIRS=\
+ qsslcertificate \
+ qsslcipher \
+ qsslerror \
+ qsslsocket \
+ qsslkey \
+