summaryrefslogtreecommitdiff
path: root/xmlsecurity
diff options
context:
space:
mode:
authorJoachim Lingner <jl@openoffice.org>2009-11-05 16:55:26 +0100
committerJoachim Lingner <jl@openoffice.org>2009-11-05 16:55:26 +0100
commit1e0bc66d16aee28ce8bd9582ea32178c63841902 (patch)
tree7650ea4b2ddb426861221c51c5c0eb286b759101 /xmlsecurity
parent639e8080784f9b04efbb2d97e9f1b6b82fba24dc (diff)
jl137: #103420# better logging
Diffstat (limited to 'xmlsecurity')
-rw-r--r--xmlsecurity/source/xmlsec/nss/secerror.cxx19
-rw-r--r--xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx176
2 files changed, 104 insertions, 91 deletions
diff --git a/xmlsecurity/source/xmlsec/nss/secerror.cxx b/xmlsecurity/source/xmlsec/nss/secerror.cxx
index 1bd7ed126f33..04406cce499e 100644
--- a/xmlsecurity/source/xmlsec/nss/secerror.cxx
+++ b/xmlsecurity/source/xmlsec/nss/secerror.cxx
@@ -69,7 +69,8 @@ printChainFailure(FILE *outfile, CERTVerifyLog *log)
{
unsigned int errorFlags = 0;
unsigned int depth = (unsigned int)-1;
- const char * specificError = NULL;
+ const char * specificError = NULL;
+ const char * issuer = NULL;
CERTVerifyLogNode *node = NULL;
if (log->count > 0)
@@ -87,6 +88,7 @@ printChainFailure(FILE *outfile, CERTVerifyLog *log)
fprintf(outfile," ERROR %ld: %s\n", node->error,
getCertError(node->error));
specificError = NULL;
+ issuer = NULL;
switch (node->error)
{
case SEC_ERROR_INADEQUATE_KEY_USAGE:
@@ -134,17 +136,24 @@ printChainFailure(FILE *outfile, CERTVerifyLog *log)
break;
}
case SEC_ERROR_UNKNOWN_ISSUER:
+ specificError = "Unknown issuer:";
+ issuer = node->cert->issuerName;
+ break;
case SEC_ERROR_UNTRUSTED_ISSUER:
+ specificError = "Untrusted issuer:";
+ issuer = node->cert->issuerName;
+ break;
case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
- specificError = node->cert->issuerName;
+ specificError = "Expired issuer certificate:";
+ issuer = node->cert->issuerName;
break;
default:
break;
}
if (specificError)
- {
- fprintf(stderr,"%s\n",specificError);
- }
+ fprintf(stderr,"%s\n", specificError);
+ if (issuer)
+ fprintf(stderr, "%s\n", issuer);
}
}
}
diff --git a/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx
index 914fd520f9de..6f4e75ed2b8e 100644
--- a/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx
+++ b/xmlsecurity/source/xmlsec/nss/securityenvironment_nssimpl.cxx
@@ -86,6 +86,14 @@ extern X509Certificate_NssImpl* NssCertToXCert( CERTCertificate* cert ) ;
extern X509Certificate_NssImpl* NssPrivKeyToXCert( SECKEYPrivateKey* ) ;
+struct UsageDescription
+{
+ SECCertificateUsage usage;
+ char const * const description;
+};
+
+
+
char* GetPasswordFunction( PK11SlotInfo* pSlot, PRBool bRetry, void* /*arg*/ )
{
uno::Reference< lang::XMultiServiceFactory > xMSF( ::comphelper::getProcessServiceFactory() );
@@ -756,7 +764,7 @@ verifyCertificate( const Reference< csss::XCertificate >& aCert,
const Sequence< Reference< csss::XCertificate > >& intermediateCerts )
throw( ::com::sun::star::uno::SecurityException, ::com::sun::star::uno::RuntimeException )
{
- sal_Int32 validity = 0;
+ sal_Int32 validity = csss::CertificateValidity::INVALID;
const X509Certificate_NssImpl* xcert ;
const CERTCertificate* cert ;
::std::vector<CERTCertificate*> vecTmpNSSCertificates;
@@ -769,16 +777,16 @@ verifyCertificate( const Reference< csss::XCertificate >& aCert,
OUStringToOString(
aCert->getSubjectName(), osl_getThreadTextEncoding()).getStr());
-
xcert = reinterpret_cast<X509Certificate_NssImpl*>(
sal::static_int_cast<sal_uIntPtr>(xCertTunnel->getSomething( X509Certificate_NssImpl::getUnoTunnelId() ))) ;
if( xcert == NULL ) {
throw RuntimeException() ;
}
- //ToDo CERT_PKIXVerifyCert does not take a db as argument. It will therefore
+ //CERT_PKIXVerifyCert does not take a db as argument. It will therefore
//internally use CERT_GetDefaultCertDB
//Make sure m_pHandler is the default DB
+ OSL_ASSERT(m_pHandler == CERT_GetDefaultCertDB());
CERTCertDBHandle * certDb = m_pHandler != NULL ? m_pHandler : CERT_GetDefaultCertDB();
cert = xcert->getNssCert() ;
if( cert != NULL )
@@ -820,11 +828,10 @@ verifyCertificate( const Reference< csss::XCertificate >& aCert,
log.head = log.tail = NULL;
log.count = 0;
-
CERT_EnableOCSPChecking(certDb);
CERT_DisableOCSPDefaultResponder(certDb);
CERTValOutParam cvout[5];
- CERTValInParam cvin[4];
+ CERTValInParam cvin[3];
cvin[0].type = cert_pi_useAIACertFetch;
cvin[0].value.scalar.b = PR_TRUE;
@@ -838,6 +845,15 @@ verifyCertificate( const Reference< csss::XCertificate >& aCert,
//We check both leaf and chain.
//It is enough if one revocation method has fresh info,
//but at least one must have some. Otherwise validation fails.
+ //!!! using leaf test and CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE
+ // when validating a root certificate will result in "revoked". Usually
+ //there is no revocation information available for the root cert because
+ //it must be trusted anyway and it does itself issue revocation information.
+ //When we use the flag here and OOo shows the certification path then the root
+ //cert is invalid while all other can be valid. It would probably best if
+ //this interface method returned the whole chain.
+ //Otherwise we need to check if the certificate is self-signed and if it is
+ //then not use the flag when doing the leaf-test.
rev.leafTests.cert_rev_flags_per_method[cert_revocation_method_crl] =
CERT_REV_M_TEST_USING_THIS_METHOD
| CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE;
@@ -847,8 +863,8 @@ verifyCertificate( const Reference< csss::XCertificate >& aCert,
rev.leafTests.number_of_preferred_methods = 0;
rev.leafTests.preferred_methods = NULL;
rev.leafTests.cert_rev_method_independent_flags =
- CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST
- | CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE;
+ CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST;
+// | CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE;
rev.chainTests.number_of_defined_methods = 2;
rev.chainTests.cert_rev_flags_per_method = revFlagsChain;
@@ -861,12 +877,13 @@ verifyCertificate( const Reference< csss::XCertificate >& aCert,
rev.chainTests.number_of_preferred_methods = 0;
rev.chainTests.preferred_methods = NULL;
rev.chainTests.cert_rev_method_independent_flags =
- CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST
- | CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE;
+ CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST;
+// | CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE;
+
cvin[1].type = cert_pi_revocationFlags;
cvin[1].value.pointer.revocation = &rev;
- // does not work
+ // does not work, not implemented yet in 3.12.4
// cvin[2].type = cert_pi_keyusage;
// cvin[2].value.scalar.ui = KU_DIGITAL_SIGNATURE;
cvin[2].type = cert_pi_end;
@@ -875,15 +892,15 @@ verifyCertificate( const Reference< csss::XCertificate >& aCert,
cvout[0].value.pointer.cert = NULL;
cvout[1].type = cert_po_errorLog;
cvout[1].value.pointer.log = &log;
- cvout[2].type = cert_po_usages;
- cvout[2].value.scalar.usages = 0;
- cvout[3].type = cert_po_keyUsage;
- cvout[3].value.scalar.usages = 0;
- cvout[4].type = cert_po_end;
-
-
- validity = csss::CertificateValidity::INVALID;
+ cvout[2].type = cert_po_end;
+ // We check SSL server certificates, CA certificates and signing sertificates.
+ //
+ // ToDo check keyusage, looking at CERT_KeyUsageAndTypeForCertUsage (
+ // mozilla/security/nss/lib/certdb/certdb.c indicates that
+ // certificateUsageSSLClient, certificateUsageSSLServer and certificateUsageSSLCA
+ // are sufficient. They cover the key usages for digital signature, key agreement
+ // and encipherment and certificate signature
//never use the following usages because they are not checked properly
// certificateUsageUserCertImport
@@ -891,81 +908,74 @@ verifyCertificate( const Reference< csss::XCertificate >& aCert,
// certificateUsageAnyCA
// certificateUsageProtectedObjectSigner
-
-
-
- SECCertificateUsage usage =
- certificateUsageEmailSigner |
- certificateUsageEmailRecipient |
- certificateUsageSSLCA |
- certificateUsageSSLServer |
- certificateUsageSSLClient |
- certificateUsageStatusResponder;
-
- fprintf(stderr,"### usage %x \n", (int) usage);
- fprintf(stderr,"### usage %d\n", (int) (certificateUsageSSLCA | certificateUsageSSLServer));
- status = CERT_PKIXVerifyCert(const_cast<CERTCertificate *>(cert), 0,
- cvin, cvout, NULL);
-
-// //JL: We must not pass a particular usage in the requiredUsages argument (the 4th) because,
-// //then ONLY these are verified. For example, we pass
-// //certificateUsageSSLClient | certificateUsageSSLServer. Then checking a certificate which
-// // is a valid certificateUsageEmailSigner but no certificateUsageSSLClient | certificateUsageSSLServer
-// //will result in CertificateValidity::INVALID.
-// //Only if the argument "requiredUsages" has a value (other than zero)
-// //then the function will return SECFailure in case
-// //the certificate is not suitable for the provided usage. That is, in the previous
-// //example the function returns SECFailure.
-
-
- if( status == SECSuccess )
+ UsageDescription arUsages[] =
{
- OSL_TRACE("[xmlsecurity] CERT_PKIXVerifyCert returned SECSuccess.");
- //When an intermediate or root certificate is checked then we expect the usage
- //certificateUsageSSLCA. This, however, will be only set when in the trust settings dialog
- //the button "This certificate can identify websites" is checked. If for example only
- //"This certificate can identify mail users" is set then the end certificate can
- //be validated and the returned usage will conain certificateUsageEmailRecipient.
- //But checking directly the root or intermediate certificate will fail. In the
- //certificate path view the end certificate will be shown as valid but the others
- //will be displayed as invalid.
-
- validity = csss::CertificateValidity::VALID;
- CERTCertificate * issuerCert = cvout[0].value.pointer.cert;
- if (issuerCert)
- {
- OSL_TRACE("[xmlsecurity] Root certificate: %s \n", issuerCert->subjectName);
- CERT_DestroyCertificate(issuerCert);
- };
+ {certificateUsageSSLClient, "certificateUsageSSLClient" },
+ {certificateUsageSSLServer, "certificateUsageSSLServer" },
+ {certificateUsageSSLCA, "certificateUsageSSLCA" },
+ {certificateUsageEmailSigner, "certificateUsageEmailSigner"}, //only usable for end certs
+// {certificateUsageEmailRecipient, "certificateUsageEmailRecipient"},
+// {certificateUsageObjectSigner, "certificateUsageObjectSigner"}
+ };
+
+ int numUsages = sizeof(arUsages) / sizeof(UsageDescription);
+ for (int i = 0; i < numUsages; i++)
+ {
+ OSL_TRACE("[xmlsecurity] Testing usage %d of %d: %s (0x%x)", i + 1,
+ numUsages, arUsages[i].description, (int) arUsages[i].usage);
- OSL_TRACE("[xmlsecurity] Usage: %X \n", cvout[2].value.scalar.usages);
- OSL_TRACE("[xmlsecurity] Key usage: %X \n", cvout[3].value.scalar.usages);
+ status = CERT_PKIXVerifyCert(const_cast<CERTCertificate *>(cert), arUsages[i].usage,
+ cvin, cvout, NULL);
+ if( status == SECSuccess )
+ {
+ OSL_TRACE("[xmlsecurity] CERT_PKIXVerifyCert returned SECSuccess.");
+ //When an intermediate or root certificate is checked then we expect the usage
+ //certificateUsageSSLCA. This, however, will be only set when in the trust settings dialog
+ //the button "This certificate can identify websites" is checked. If for example only
+ //"This certificate can identify mail users" is set then the end certificate can
+ //be validated and the returned usage will conain certificateUsageEmailRecipient.
+ //But checking directly the root or intermediate certificate will fail. In the
+ //certificate path view the end certificate will be shown as valid but the others
+ //will be displayed as invalid.
+
+ validity = csss::CertificateValidity::VALID;
+ OSL_TRACE("[xmlsecurity] Certificate is valid.\n");
+ CERTCertificate * issuerCert = cvout[0].value.pointer.cert;
+ if (issuerCert)
+ {
+ OSL_TRACE("[xmlsecurity] Root certificate: %s", issuerCert->subjectName);
+ CERT_DestroyCertificate(issuerCert);
+ };
- }
- else
- {
+ break;
+ }
+ else
+ {
#if OSL_DEBUG_LEVEL > 1
- PRIntn err = PR_GetError();
- fprintf(stderr, "Error: , %d = %s\n", err, getCertError(err));
+ PRIntn err = PR_GetError();
+ fprintf(stderr, "Error: , %d = %s\n", err, getCertError(err));
#endif
- /* Display validation results */
- if ( log.count > 0)
- {
- CERTVerifyLogNode *node = NULL;
+ /* Display validation results */
+ if ( log.count > 0)
+ {
+ CERTVerifyLogNode *node = NULL;
#if OSL_DEBUG_LEVEL > 1
- printChainFailure(stderr, &log);
+ printChainFailure(stderr, &log);
#endif
- for (node = log.head; node; node = node->next) {
- if (node->cert)
- CERT_DestroyCertificate(node->cert);
+ for (node = log.head; node; node = node->next) {
+ if (node->cert)
+ CERT_DestroyCertificate(node->cert);
+ }
+ log.head = log.tail = NULL;
+ log.count = 0;
}
+ OSL_TRACE("[xmlsecurity] Certificate is invalid.");
}
-
}
+
}
else
{
-
validity = ::com::sun::star::security::CertificateValidity::INVALID ;
}
@@ -976,12 +986,6 @@ verifyCertificate( const Reference< csss::XCertificate >& aCert,
OSL_TRACE("[xmlsecurity] Destroying temporary certificate");
CERT_DestroyCertificate(*cert_i);
}
-#if OSL_DEBUG_LEVEL > 1
- if (validity == ::com::sun::star::security::CertificateValidity::VALID)
- OSL_TRACE("[xmlsecurity] Certificate is valid.");
- else
- OSL_TRACE("[xmlsecurity] Certificate is invalid.");
-#endif
return validity ;
}