diff options
author | Peter Hartmann <peter.hartmann@nokia.com> | 2010-06-01 14:50:55 (GMT) |
---|---|---|
committer | Peter Hartmann <peter.hartmann@nokia.com> | 2010-06-02 09:46:44 (GMT) |
commit | 0f16c7ce8dcd6f4905d14875088c55148e41366a (patch) | |
tree | d0b6a19e3fe57b55711ff7a7b6c48e9a15f457e4 | |
parent | cd50f97a9f09eece645c9d7d01cb14c04521a915 (diff) | |
download | Qt-0f16c7ce8dcd6f4905d14875088c55148e41366a.zip Qt-0f16c7ce8dcd6f4905d14875088c55148e41366a.tar.gz Qt-0f16c7ce8dcd6f4905d14875088c55148e41366a.tar.bz2 |
QSslCertificate: support large serial numbers
We were calling an OpenSSL function that returned a long for the serial
number; sometimes serial numbers are too big to fit into a long (up to
20 octets). In that case, do not convert the serial number to decimal,
but just output the hexadecimal value.
Reviewed-by: Zeno Albisser
Task-number: QTBUG-9973
-rw-r--r-- | src/network/ssl/qsslcertificate.cpp | 23 | ||||
-rw-r--r-- | tests/auto/qsslcertificate/more-certificates/cert-large-serial-number.pem | 14 | ||||
-rw-r--r-- | tests/auto/qsslcertificate/tst_qsslcertificate.cpp | 13 |
3 files changed, 46 insertions, 4 deletions
diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp index fd647e2..31c5ed1 100644 --- a/src/network/ssl/qsslcertificate.cpp +++ b/src/network/ssl/qsslcertificate.cpp @@ -259,13 +259,28 @@ QByteArray QSslCertificate::version() const /*! Returns the certificate's serial number string in decimal format. + In case the serial number cannot be converted to decimal format + (i.e. if it is bigger than 4294967295, which means it does not fit into 4 bytes), + its hexadecimal version is returned. */ QByteArray QSslCertificate::serialNumber() const { - if (d->serialNumberString.isEmpty() && d->x509) - d->serialNumberString = - QByteArray::number(qlonglong(q_ASN1_INTEGER_get(d->x509->cert_info->serialNumber))); - + if (d->serialNumberString.isEmpty() && d->x509) { + ASN1_INTEGER *serialNumber = d->x509->cert_info->serialNumber; + // if we cannot convert to a long, just output the hexadecimal number + if (serialNumber->length > 4) { + QByteArray hexString; + hexString.reserve(serialNumber->length * 3); + for (int a = 0; a < serialNumber->length; ++a) { + hexString += QByteArray::number(serialNumber->data[a], 16).rightJustified(2, '0'); + hexString += ':'; + } + hexString.chop(1); + d->serialNumberString = hexString; + } else { + d->serialNumberString = QByteArray::number(qlonglong(q_ASN1_INTEGER_get(serialNumber))); + } + } return d->serialNumberString; } diff --git a/tests/auto/qsslcertificate/more-certificates/cert-large-serial-number.pem b/tests/auto/qsslcertificate/more-certificates/cert-large-serial-number.pem new file mode 100644 index 0000000..ecb6c35 --- /dev/null +++ b/tests/auto/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/qsslcertificate/tst_qsslcertificate.cpp b/tests/auto/qsslcertificate/tst_qsslcertificate.cpp index c76c11f..505b867 100644 --- a/tests/auto/qsslcertificate/tst_qsslcertificate.cpp +++ b/tests/auto/qsslcertificate/tst_qsslcertificate.cpp @@ -109,6 +109,7 @@ private slots: void task256066toPem(); void nulInCN(); void nulInSan(); + void largeSerialNumber(); // ### add tests for certificate bundles (multiple certificates concatenated into a single // structure); both PEM and DER formatted #endif @@ -786,6 +787,18 @@ void tst_QSslCertificate::nulInSan() 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")); +} + #endif // QT_NO_OPENSSL QTEST_MAIN(tst_QSslCertificate) |