diff --git a/mozilla/browser/locales/en-US/chrome/overrides/netError.dtd b/mozilla/browser/locales/en-US/chrome/overrides/netError.dtd index 9487d491575..a8e546bb704 100644 --- a/mozilla/browser/locales/en-US/chrome/overrides/netError.dtd +++ b/mozilla/browser/locales/en-US/chrome/overrides/netError.dtd @@ -123,6 +123,17 @@ "> + + +
  • This could be a problem with the server's configuration, or it could be +someone trying to impersonate the server.
  • +
  • If you have connected to this server successfully in the past, the error may +be temporary, and you can try again later.
  • +
  • You can see and change your current list of servers with known security problems + in your advanced encryption settings.
  • + +"> diff --git a/mozilla/camino/embed-replacements/locale/en-US/global/netError.dtd b/mozilla/camino/embed-replacements/locale/en-US/global/netError.dtd index 406bde0de08..dff0da078b2 100644 --- a/mozilla/camino/embed-replacements/locale/en-US/global/netError.dtd +++ b/mozilla/camino/embed-replacements/locale/en-US/global/netError.dtd @@ -54,6 +54,14 @@ The page you are trying to view can not be shown because the authenticity of the received data could not be verified.

    "> + + +
  • This could be a problem with the server's configuration, or it could be someone trying to impersonate the server.
  • +
  • If you have connected to this server successfully in the past, the error may be temporary, and you can try again later.
  • +
  • You can see and change your current list of servers with known security problems in your advanced encryption settings.
  • + +"> + Attack sites try to install programs that steal private information, use your computer to attack others, or damage your system.

    diff --git a/mozilla/docshell/base/nsDocShell.cpp b/mozilla/docshell/base/nsDocShell.cpp index 1d33b089882..20bda6c3e2c 100644 --- a/mozilla/docshell/base/nsDocShell.cpp +++ b/mozilla/docshell/base/nsDocShell.cpp @@ -2931,6 +2931,15 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI *aURI, error.AssignLiteral("netTimeout"); } else if (NS_ERROR_GET_MODULE(aError) == NS_ERROR_MODULE_SECURITY) { + nsCOMPtr nsserr = + do_GetService(NS_NSS_ERRORS_SERVICE_CONTRACTID); + + PRUint32 errorClass; + if (!nsserr || + NS_FAILED(nsserr->GetErrorClass(aError, &errorClass))) { + errorClass = nsINSSErrorsService::ERROR_CLASS_SSL_PROTOCOL; + } + nsCOMPtr securityInfo; nsCOMPtr tsi; if (aFailedChannel) @@ -2942,20 +2951,23 @@ nsDocShell::DisplayLoadError(nsresult aError, nsIURI *aURI, } else { // No channel, let's obtain the generic error message - nsCOMPtr nsserr = - do_GetService(NS_NSS_ERRORS_SERVICE_CONTRACTID); if (nsserr) { nsserr->GetErrorMessage(aError, messageStr); } } - if (!messageStr.IsEmpty()) - error.AssignLiteral("nssFailure2"); + if (!messageStr.IsEmpty()) { + if (errorClass == nsINSSErrorsService::ERROR_CLASS_BAD_CERT) { + error.AssignLiteral("nssBadCert"); + } else { + error.AssignLiteral("nssFailure2"); + } + } } else if (NS_ERROR_PHISHING_URI == aError || NS_ERROR_MALWARE_URI == aError) { nsCAutoString host; aURI->GetHost(host); CopyUTF8toUTF16(host, formatStrs[0]); formatStrCount = 1; - + // Malware and phishing detectors may want to use an alternate error // page, but if the pref's not set, we'll fall back on the standard page nsXPIDLCString alternateErrorPage; diff --git a/mozilla/docshell/resources/content/netError.xhtml b/mozilla/docshell/resources/content/netError.xhtml index 886410ebeb3..01d24593633 100644 --- a/mozilla/docshell/resources/content/netError.xhtml +++ b/mozilla/docshell/resources/content/netError.xhtml @@ -202,6 +202,7 @@

    &proxyConnectFailure.title;

    &contentEncodingError.title;

    &nssFailure2.title;

    +

    &nssBadCert.title;

    &malwareBlocked.title;

    @@ -222,6 +223,7 @@
    &proxyConnectFailure.longDesc;
    &contentEncodingError.longDesc;
    &nssFailure2.longDesc;
    +
    &nssBadCert.longDesc;
    &malwareBlocked.longDesc;
    diff --git a/mozilla/dom/locales/en-US/chrome/netError.dtd b/mozilla/dom/locales/en-US/chrome/netError.dtd index 4ea705029c3..d99b2aebd6e 100644 --- a/mozilla/dom/locales/en-US/chrome/netError.dtd +++ b/mozilla/dom/locales/en-US/chrome/netError.dtd @@ -54,6 +54,14 @@ The page you are trying to view can not be shown because the authenticity of the received data could not be verified.

    • Please contact the web site owners to inform them of this problem.
    "> + + +
  • This could be a problem with the server's configuration, or it could be someone trying to impersonate the server.
  • +
  • If you have connected to this server successfully in the past, the error may be temporary, and you can try again later.
  • +
  • You can see and change your current list of servers with known security problems in your advanced encryption settings.
  • + +"> + Attack sites try to install programs that steal private information, use your computer to attack others, or damage your system.

    diff --git a/mozilla/netwerk/base/public/nsINSSErrorsService.idl b/mozilla/netwerk/base/public/nsINSSErrorsService.idl index 05f0d44d3fc..871bade60d7 100644 --- a/mozilla/netwerk/base/public/nsINSSErrorsService.idl +++ b/mozilla/netwerk/base/public/nsINSSErrorsService.idl @@ -39,7 +39,7 @@ #include "nsISupports.idl" -[scriptable, uuid(c6ac6e5d-9db1-4cad-bedc-e2d226913c21)] +[scriptable, uuid(3a5c7a0f-f5da-4a8b-a748-d7c5a528f33b)] interface nsINSSErrorsService : nsISupports { /** @@ -61,4 +61,14 @@ interface nsINSSErrorsService : nsISupports * return A localized human readable error explanation. */ AString getErrorMessage(in nsresult aXPCOMErrorCode); + + /** + * Function will fail if aXPCOMErrorCode is not an NSS error code. + * @param aXPCOMErrorCode An error code obtain using getXPCOMFromNSSError + * return the + */ + PRUint32 getErrorClass(in nsresult aXPCOMErrorCode); + + const unsigned long ERROR_CLASS_SSL_PROTOCOL = 1; + const unsigned long ERROR_CLASS_BAD_CERT = 2; }; diff --git a/mozilla/security/manager/locales/en-US/chrome/pipnss/pipnss.properties b/mozilla/security/manager/locales/en-US/chrome/pipnss/pipnss.properties index 5b71d083798..a08e96f687c 100644 --- a/mozilla/security/manager/locales/en-US/chrome/pipnss/pipnss.properties +++ b/mozilla/security/manager/locales/en-US/chrome/pipnss/pipnss.properties @@ -337,12 +337,24 @@ PSMERR_HostReusedIssuerSerial=You have received an invalid certificate. Please SSLConnectionErrorPrefix=An error occurred during a connection to %S. -certErrorIntro=An error occurred during a connection to %S because it uses an invalid security certificate. -certErrorUntrusted=The certificate is not trusted or its issuer certificate is invalid. -certErrorMismatch=The certificate is not valid for domain name %S. -certErrorExpired=The certificate has expired on %S. +certErrorIntro=%S uses an invalid security certificate. + +certErrorTrust_SelfSigned=The certificate is not trusted because it is self signed. +certErrorTrust_UnknownIssuer=The certificate is not trusted because the issuer certificate is unknown. +certErrorTrust_CaInvalid=The certificate is not trusted because it was issued by an invalid CA certificate. +certErrorTrust_Issuer=The certificate is not trusted because the issuer certificate is not trusted. +certErrorTrust_ExpiredIssuer=The certificate is not trusted because the issuer certificate has expired. +certErrorTrust_Untrusted=The certificate does not come from a trusted source. + +certErrorMismatch=The certificate is not valid for the name %S. +certErrorMismatchSingle=The certificate is only valid for name %S. +certErrorMismatchMultiple=The certificate is only valid for the following names: + +certErrorExpired=The certificate expired on %S. certErrorNotYetValid=The certificate will not be valid until %S. +certErrorCodePrefix=(Error code: %S) + CertInfoIssuedFor=Issued to: CertInfoIssuedBy=Issued by: CertInfoValid=Valid diff --git a/mozilla/security/manager/ssl/public/nsIX509Cert3.idl b/mozilla/security/manager/ssl/public/nsIX509Cert3.idl index 267135ecb55..c32e301feba 100644 --- a/mozilla/security/manager/ssl/public/nsIX509Cert3.idl +++ b/mozilla/security/manager/ssl/public/nsIX509Cert3.idl @@ -42,7 +42,7 @@ interface nsICertVerificationListener; /** * Extending nsIX509Cert */ -[scriptable, uuid(1362ffab-a683-4504-8038-25ce63b45370)] +[scriptable, uuid(aa67eb02-ccc8-4f55-84da-bcafff9265ae)] interface nsIX509Cert3 : nsIX509Cert2 { /** @@ -72,6 +72,8 @@ interface nsIX509Cert3 : nsIX509Cert2 { void exportAsCMS(in unsigned long chainMode, out unsigned long length, [retval, array, size_is(length)] out octet data); + + readonly attribute boolean isSelfSigned; }; [scriptable, uuid(2fd0a785-9f2d-4327-8871-8c3e0783891d)] diff --git a/mozilla/security/manager/ssl/src/nsNSSCertificate.cpp b/mozilla/security/manager/ssl/src/nsNSSCertificate.cpp index 6567fa5a6f1..a1a8c542bee 100644 --- a/mozilla/security/manager/ssl/src/nsNSSCertificate.cpp +++ b/mozilla/security/manager/ssl/src/nsNSSCertificate.cpp @@ -221,6 +221,19 @@ nsNSSCertificate::GetCertType(PRUint32 *aCertType) return NS_OK; } +NS_IMETHODIMP +nsNSSCertificate::GetIsSelfSigned(PRBool *aIsSelfSigned) +{ + NS_ENSURE_ARG(aIsSelfSigned); + + nsNSSShutDownPreventionLock locker; + if (isAlreadyShutDown()) + return NS_ERROR_NOT_AVAILABLE; + + *aIsSelfSigned = mCert->isRoot; + return NS_OK; +} + nsresult nsNSSCertificate::MarkForPermDeletion() { diff --git a/mozilla/security/manager/ssl/src/nsNSSComponent.cpp b/mozilla/security/manager/ssl/src/nsNSSComponent.cpp index 0ea5da373ee..208002fb65b 100644 --- a/mozilla/security/manager/ssl/src/nsNSSComponent.cpp +++ b/mozilla/security/manager/ssl/src/nsNSSComponent.cpp @@ -2228,6 +2228,38 @@ nsNSSComponent::GetXPCOMFromNSSError(PRInt32 aNSPRCode, nsresult *aXPCOMErrorCod return NS_OK; } +NS_IMETHODIMP +nsNSSComponent::GetErrorClass(nsresult aXPCOMErrorCode, PRUint32 *aErrorClass) +{ + NS_ENSURE_ARG(aErrorClass); + + if (NS_ERROR_GET_MODULE(aXPCOMErrorCode) != NS_ERROR_MODULE_SECURITY + || NS_ERROR_GET_SEVERITY(aXPCOMErrorCode) != NS_ERROR_SEVERITY_ERROR) + return NS_ERROR_FAILURE; + + PRInt32 aNSPRCode = -1 * NS_ERROR_GET_CODE(aXPCOMErrorCode); + + if (!IS_SEC_ERROR(aNSPRCode) && !IS_SSL_ERROR(aNSPRCode)) + return NS_ERROR_FAILURE; + + switch (aNSPRCode) + { + case SEC_ERROR_UNKNOWN_ISSUER: + case SEC_ERROR_CA_CERT_INVALID: + case SEC_ERROR_UNTRUSTED_ISSUER: + case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: + case SEC_ERROR_UNTRUSTED_CERT: + case SSL_ERROR_BAD_CERT_DOMAIN: + case SEC_ERROR_EXPIRED_CERTIFICATE: + *aErrorClass = ERROR_CLASS_BAD_CERT; + break; + default: + *aErrorClass = ERROR_CLASS_SSL_PROTOCOL; + break; + } + return NS_OK; +} + NS_IMETHODIMP nsNSSComponent::GetErrorMessage(nsresult aXPCOMErrorCode, nsAString &aErrorMessage) { diff --git a/mozilla/security/manager/ssl/src/nsNSSErrors.cpp b/mozilla/security/manager/ssl/src/nsNSSErrors.cpp index 85aca4341d9..6c6cde158ae 100644 --- a/mozilla/security/manager/ssl/src/nsNSSErrors.cpp +++ b/mozilla/security/manager/ssl/src/nsNSSErrors.cpp @@ -364,16 +364,30 @@ nsNSSErrors::getErrorMessageFromCode(PRInt32 err, if (NS_SUCCEEDED(rv)) { returnedMessage.Append(defMsg); - returnedMessage.Append(NS_LITERAL_STRING(" ")); + returnedMessage.Append(NS_LITERAL_STRING("\n")); } nsCString error_id(nss_error_id_str); ToLowerCase(error_id); NS_ConvertASCIItoUTF16 idU(error_id); - returnedMessage.Append(NS_LITERAL_STRING("(")); - returnedMessage.Append(idU); - returnedMessage.Append(NS_LITERAL_STRING(")")); + const PRUnichar *params[1]; + params[0] = idU.get(); + + nsString formattedString; + rv = component->PIPBundleFormatStringFromName("certErrorCodePrefix", + params, 1, + formattedString); + if (NS_SUCCEEDED(rv)) { + returnedMessage.Append(NS_LITERAL_STRING("\n")); + returnedMessage.Append(formattedString); + returnedMessage.Append(NS_LITERAL_STRING("\n")); + } + else { + returnedMessage.Append(NS_LITERAL_STRING("(")); + returnedMessage.Append(idU); + returnedMessage.Append(NS_LITERAL_STRING(")")); + } } return NS_OK; diff --git a/mozilla/security/manager/ssl/src/nsNSSIOLayer.cpp b/mozilla/security/manager/ssl/src/nsNSSIOLayer.cpp index ecf4f63b51a..bc843fa9c96 100644 --- a/mozilla/security/manager/ssl/src/nsNSSIOLayer.cpp +++ b/mozilla/security/manager/ssl/src/nsNSSIOLayer.cpp @@ -599,7 +599,10 @@ void nsSSLIOLayerHelpers::Cleanup() } static nsresult -getErrorMessage(PRInt32 err, const nsString &host, +getErrorMessage(PRInt32 err, + const nsString &host, + PRInt32 port, + PRBool externalErrorReporting, nsINSSComponent *component, nsString &returnedMessage) { @@ -610,7 +613,24 @@ getErrorMessage(PRInt32 err, const nsString &host, if (host.Length()) { - params[0] = host.get(); + nsString hostWithPort; + + // For now, hide port when it's 443 and we're reporting the error using + // external reporting. In the future a better mechanism should be used + // to make a decision about showing the port number, possibly by requiring + // the context object to implement a specific interface. + // The motivation is that Mozilla browser would like to hide the port number + // in error pages in the common case. + + if (externalErrorReporting && port == 443) { + params[0] = host.get(); + } + else { + hostWithPort = host; + hostWithPort.AppendLiteral(":"); + hostWithPort.AppendInt(port); + params[0] = hostWithPort.get(); + } nsString formattedString; rv = component->PIPBundleFormatStringFromName("SSLConnectionErrorPrefix", @@ -619,7 +639,7 @@ getErrorMessage(PRInt32 err, const nsString &host, if (NS_SUCCEEDED(rv)) { returnedMessage.Append(formattedString); - returnedMessage.Append(NS_LITERAL_STRING("\n")); + returnedMessage.Append(NS_LITERAL_STRING("\n\n")); } } @@ -633,10 +653,15 @@ getErrorMessage(PRInt32 err, const nsString &host, static nsresult getInvalidCertErrorMessage(PRUint32 multipleCollectedErrors, - PRInt32 errorCodeToReport, + PRErrorCode errorCodeToReport, + PRErrorCode errTrust, + PRErrorCode errMismatch, + PRErrorCode errExpired, const nsString &host, const nsString &hostWithPort, + PRInt32 port, nsIX509Cert* ix509, + PRBool externalErrorReporting, nsINSSComponent *component, nsString &returnedMessage) { @@ -645,27 +670,65 @@ getInvalidCertErrorMessage(PRUint32 multipleCollectedErrors, const PRUnichar *params[1]; nsresult rv; - if (hostWithPort.Length()) - { + // For now, hide port when it's 443 and we're reporting the error using + // external reporting. In the future a better mechanism should be used + // to make a decision about showing the port number, possibly by requiring + // the context object to implement a specific interface. + // The motivation is that Mozilla browser would like to hide the port number + // in error pages in the common case. + + if (externalErrorReporting && port == 443) + params[0] = host.get(); + else params[0] = hostWithPort.get(); - nsString formattedString; - rv = component->PIPBundleFormatStringFromName("certErrorIntro", - params, 1, - formattedString); - if (NS_SUCCEEDED(rv)) - { - returnedMessage.Append(formattedString); - returnedMessage.Append(NS_LITERAL_STRING("\n")); - } + nsString formattedString; + rv = component->PIPBundleFormatStringFromName("certErrorIntro", + params, 1, + formattedString); + if (NS_SUCCEEDED(rv)) + { + returnedMessage.Append(formattedString); + returnedMessage.Append(NS_LITERAL_STRING("\n\n")); } if (multipleCollectedErrors & nsICertOverrideService::ERROR_UNTRUSTED) { params[0] = host.get(); + const char *errorID = nsnull; + nsCOMPtr cert3 = do_QueryInterface(ix509); + if (cert3) { + PRBool isSelfSigned; + if (NS_SUCCEEDED(cert3->GetIsSelfSigned(&isSelfSigned)) + && isSelfSigned) { + errorID = "certErrorTrust_SelfSigned"; + } + } + + if (!errorID) { + switch (errTrust) { + case SEC_ERROR_UNKNOWN_ISSUER: + errorID = "certErrorTrust_UnknownIssuer"; + break; + case SEC_ERROR_CA_CERT_INVALID: + errorID = "certErrorTrust_CaInvalid"; + break; + case SEC_ERROR_UNTRUSTED_ISSUER: + errorID = "certErrorTrust_Issuer"; + break; + case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: + errorID = "certErrorTrust_ExpiredIssuer"; + break; + case SEC_ERROR_UNTRUSTED_CERT: + default: + errorID = "certErrorTrust_Untrusted"; + break; + } + } + nsString formattedString; - rv = component->GetPIPNSSBundleString("certErrorUntrusted", + rv = component->GetPIPNSSBundleString(errorID, formattedString); if (NS_SUCCEEDED(rv)) { @@ -676,16 +739,125 @@ getInvalidCertErrorMessage(PRUint32 multipleCollectedErrors, if (multipleCollectedErrors & nsICertOverrideService::ERROR_MISMATCH) { - params[0] = host.get(); + PRBool useSAN = PR_TRUE; // subject alt name extension + PRBool multipleNames = PR_FALSE; + nsString allNames; - nsString formattedString; - rv = component->PIPBundleFormatStringFromName("certErrorMismatch", - params, 1, - formattedString); - if (NS_SUCCEEDED(rv)) - { - returnedMessage.Append(formattedString); - returnedMessage.Append(NS_LITERAL_STRING("\n")); + CERTCertificate *nssCert = NULL; + CERTCertificateCleaner nssCertCleaner(nssCert); + nsCOMPtr cert2 = do_QueryInterface(ix509, &rv); + if (cert2) + nssCert = cert2->GetCert(); + if (!nssCert) + useSAN = PR_FALSE; + + PRArenaPool *san_arena = nsnull; + SECItem altNameExtension = {siBuffer, NULL, 0 }; + CERTGeneralName *sanNameList = nsnull; + + if (useSAN) { + rv = CERT_FindCertExtension(nssCert, SEC_OID_X509_SUBJECT_ALT_NAME, + &altNameExtension); + if (rv != SECSuccess) + useSAN = PR_FALSE; + } + + if (useSAN) { + san_arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); + if (!san_arena) + useSAN = PR_FALSE; + } + + if (useSAN) { + sanNameList = CERT_DecodeAltNameExtension(san_arena, &altNameExtension); + if (!sanNameList) + useSAN = PR_FALSE; + } + + SECITEM_FreeItem(&altNameExtension, PR_FALSE); + + if (useSAN) { + CERTGeneralName *current = sanNameList; + do { + nsAutoString name; + switch (current->type) { + case certDNSName: + name.AssignASCII((char*)current->name.other.data, current->name.other.len); + if (!allNames.IsEmpty()) { + multipleNames = PR_TRUE; + allNames.Append(NS_LITERAL_STRING(" , ")); + } + allNames.Append(name); + break; + + case certIPAddress: + { + char buf[INET6_ADDRSTRLEN]; + PRNetAddr addr; + if (current->name.other.len == 4) { + addr.inet.family = PR_AF_INET; + memcpy(&addr.inet.ip, current->name.other.data, current->name.other.len); + PR_NetAddrToString(&addr, buf, sizeof(buf)); + name.AssignASCII(buf); + } else if (current->name.other.len == 16) { + addr.ipv6.family = PR_AF_INET6; + memcpy(&addr.ipv6.ip, current->name.other.data, current->name.other.len); + PR_NetAddrToString(&addr, buf, sizeof(buf)); + name.AssignASCII(buf); + } else { + /* invalid IP address */ + } + if (!name.IsEmpty()) { + if (!allNames.IsEmpty()) { + multipleNames = PR_TRUE; + allNames.Append(NS_LITERAL_STRING(" , ")); + } + allNames.Append(name); + } + break; + } + + default: // all other types of names are ignored + break; + } + current = CERT_GetNextGeneralName(current); + } while (current != sanNameList); // double linked + } + if (san_arena) + PORT_FreeArena(san_arena, PR_FALSE); + + if (!useSAN) { + char *certName = nsnull; + // certName = CERT_FindNSStringExtension(nssCert, SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME); + if (!certName) { + certName = CERT_GetCommonName(&nssCert->subject); + } + allNames.AssignASCII(certName); + PORT_Free(certName); + } + + if (multipleNames) { + nsString message; + rv = component->GetPIPNSSBundleString("certErrorMismatchMultiple", + message); + if (NS_SUCCEEDED(rv)) { + returnedMessage.Append(message); + returnedMessage.Append(NS_LITERAL_STRING("\n ")); + returnedMessage.Append(allNames); + returnedMessage.Append(NS_LITERAL_STRING(" \n")); + } + } + else { // !multipleNames + params[0] = allNames.get(); + + nsString formattedString; + rv = component->PIPBundleFormatStringFromName("certErrorMismatchSingle", + params, 1, + formattedString); + if (NS_SUCCEEDED(rv)) { + returnedMessage.Append(formattedString); + returnedMessage.Append(NS_LITERAL_STRING("\n")); + } } } @@ -745,9 +917,22 @@ getInvalidCertErrorMessage(PRUint32 multipleCollectedErrors, ToLowerCase(error_id); NS_ConvertASCIItoUTF16 idU(error_id); - returnedMessage.Append(NS_LITERAL_STRING(" (")); - returnedMessage.Append(idU); - returnedMessage.Append(NS_LITERAL_STRING(")")); + params[0] = idU.get(); + + nsString formattedString; + rv = component->PIPBundleFormatStringFromName("certErrorCodePrefix", + params, 1, + formattedString); + if (NS_SUCCEEDED(rv)) { + returnedMessage.Append(NS_LITERAL_STRING("\n")); + returnedMessage.Append(formattedString); + returnedMessage.Append(NS_LITERAL_STRING("\n")); + } + else { + returnedMessage.Append(NS_LITERAL_STRING(" (")); + returnedMessage.Append(idU); + returnedMessage.Append(NS_LITERAL_STRING(")")); + } } return NS_OK; @@ -803,12 +988,15 @@ nsHandleSSLError(nsNSSSocketInfo *socketInfo, PRInt32 err) socketInfo->GetHostName(getter_Copies(hostName)); NS_ConvertASCIItoUTF16 hostNameU(hostName); - nsString formattedString; - rv = getErrorMessage(err, hostNameU, nssComponent, formattedString); + PRInt32 port; + socketInfo->GetPort(&port); PRBool external = PR_FALSE; socketInfo->GetExternalErrorReporting(&external); + nsString formattedString; + rv = getErrorMessage(err, hostNameU, port, external, nssComponent, formattedString); + if (external) { socketInfo->SetErrorMessage(formattedString.get()); @@ -830,8 +1018,12 @@ static nsresult nsHandleInvalidCertError(nsNSSSocketInfo *socketInfo, PRUint32 multipleCollectedErrors, const nsACString &host, - const nsACString &hostWithPort, - PRInt32 err, + const nsACString &hostWithPort, + PRInt32 port, + PRErrorCode errorCodeToReport, + PRErrorCode errTrust, + PRErrorCode errMismatch, + PRErrorCode errExpired, nsIX509Cert* ix509) { nsresult rv; @@ -843,10 +1035,6 @@ nsHandleInvalidCertError(nsNSSSocketInfo *socketInfo, NS_ConvertASCIItoUTF16 hostU(host); NS_ConvertASCIItoUTF16 hostWithPortU(hostWithPort); - nsString formattedString; - rv = getInvalidCertErrorMessage(multipleCollectedErrors, err, hostU, hostWithPortU, - ix509, nssComponent, formattedString); - // What mechanism is used to inform the user? // The highest priority has the "external error reporting" feature, // if set, we'll provide the strings to be used by the nsINSSErrorsService @@ -854,6 +1042,12 @@ nsHandleInvalidCertError(nsNSSSocketInfo *socketInfo, PRBool external = PR_FALSE; socketInfo->GetExternalErrorReporting(&external); + nsString formattedString; + rv = getInvalidCertErrorMessage(multipleCollectedErrors, errorCodeToReport, ++ errTrust, errMismatch, errExpired, + hostU, hostWithPortU, port, + ix509, external, nssComponent, formattedString); + if (external) { socketInfo->SetErrorMessage(formattedString.get()); @@ -2327,11 +2521,9 @@ nsNSSBadCertHandler(void *arg, PRFileDesc *sslSocket) PRUint32 collected_errors = 0; PRUint32 remaining_display_errors = 0; - // There may be multiple problems with a cert, but we can only report - // a single error code to the caller. We'll use the first code we see. - // However, in our error string we'll use a string that mentions - // all of expired/not-yet-valid/domain-mismatch/untrusted. - PRErrorCode errorCodeToReport = SECSuccess; + PRErrorCode errorCodeTrust = SECSuccess; + PRErrorCode errorCodeMismatch = SECSuccess; + PRErrorCode errorCodeExpired = SECSuccess; char *hostname = SSL_RevealURL(sslSocket); charCleaner hostnameCleaner(hostname); @@ -2350,7 +2542,7 @@ nsNSSBadCertHandler(void *arg, PRFileDesc *sslSocket) if (hostname && hostname[0] && CERT_VerifyCertName(peerCert, hostname) != SECSuccess) { collected_errors |= nsICertOverrideService::ERROR_MISMATCH; - errorCodeToReport = SSL_ERROR_BAD_CERT_DOMAIN; + errorCodeMismatch = SSL_ERROR_BAD_CERT_DOMAIN; } { @@ -2382,10 +2574,6 @@ nsNSSBadCertHandler(void *arg, PRFileDesc *sslSocket) CERTVerifyLogNode *i_node; for (i_node = verify_log->head; i_node; i_node = i_node->next) { - if (errorCodeToReport == SECSuccess) { - errorCodeToReport = i_node->error; - } - switch (i_node->error) { case SEC_ERROR_UNKNOWN_ISSUER: @@ -2395,12 +2583,21 @@ nsNSSBadCertHandler(void *arg, PRFileDesc *sslSocket) case SEC_ERROR_UNTRUSTED_CERT: // We group all these errors as "cert not trusted" collected_errors |= nsICertOverrideService::ERROR_UNTRUSTED; + if (errorCodeTrust == SECSuccess) { + errorCodeTrust = i_node->error; + } break; case SSL_ERROR_BAD_CERT_DOMAIN: collected_errors |= nsICertOverrideService::ERROR_MISMATCH; + if (errorCodeMismatch == SECSuccess) { + errorCodeMismatch = i_node->error; + } break; case SEC_ERROR_EXPIRED_CERTIFICATE: collected_errors |= nsICertOverrideService::ERROR_TIME; + if (errorCodeExpired == SECSuccess) { + errorCodeExpired = i_node->error; + } break; default: // we are not willing to continue on any other error @@ -2496,13 +2693,26 @@ nsNSSBadCertHandler(void *arg, PRFileDesc *sslSocket) recentBadCertsService->AddBadCert(hostWithPortStringUTF16, status); } + // pick the error code to report by priority + PRErrorCode errorCodeToReport = SECSuccess; + if (remaining_display_errors & nsICertOverrideService::ERROR_UNTRUSTED) + errorCodeToReport = errorCodeTrust; + else if (remaining_display_errors & nsICertOverrideService::ERROR_MISMATCH) + errorCodeToReport = errorCodeMismatch; + else if (remaining_display_errors & nsICertOverrideService::ERROR_TIME) + errorCodeToReport = errorCodeExpired; + PR_SetError(errorCodeToReport, 0); if (!suppressMessage) { nsHandleInvalidCertError(infoObject, remaining_display_errors, hostString, - hostWithPortString, - errorCodeToReport, + hostWithPortString, + port, + errorCodeToReport, + errorCodeTrust, + errorCodeMismatch, + errorCodeExpired, ix509); } diff --git a/mozilla/toolkit/themes/pinstripe/global/netError.css b/mozilla/toolkit/themes/pinstripe/global/netError.css index 7c0e8ffc84e..7fe69b171ee 100644 --- a/mozilla/toolkit/themes/pinstripe/global/netError.css +++ b/mozilla/toolkit/themes/pinstripe/global/netError.css @@ -68,6 +68,7 @@ body[dir="rtl"] #errorPageContainer { border-bottom: 1px solid ThreeDLightShadow; padding-bottom: 1em; font-size: 130%; + white-space: -moz-pre-wrap; } #errorLongDesc { diff --git a/mozilla/toolkit/themes/winstripe/global/netError.css b/mozilla/toolkit/themes/winstripe/global/netError.css index b5347e93e25..6122233c1df 100644 --- a/mozilla/toolkit/themes/winstripe/global/netError.css +++ b/mozilla/toolkit/themes/winstripe/global/netError.css @@ -68,6 +68,7 @@ body[dir="rtl"] #errorPageContainer { border-bottom: 1px solid ThreeDLightShadow; padding-bottom: 1em; font-size: 130%; + white-space: -moz-pre-wrap; } #errorLongDesc {