Loading security/manager/ssl/src/nsNSSIOLayer.cpp +309 −226 Original line number Diff line number Diff line Loading @@ -651,51 +651,13 @@ getErrorMessage(PRInt32 err, return NS_OK; } static nsresult getInvalidCertErrorMessage(PRUint32 multipleCollectedErrors, PRErrorCode errorCodeToReport, PRErrorCode errTrust, PRErrorCode errMismatch, PRErrorCode errExpired, static void AppendErrorTextUntrusted(PRErrorCode errTrust, const nsString &host, const nsString &hostWithPort, PRInt32 port, nsIX509Cert* ix509, PRBool externalErrorReporting, nsINSSComponent *component, nsString &returnedMessage) { NS_ENSURE_ARG_POINTER(component); const PRUnichar *params[1]; nsresult rv; // 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\n")); } if (multipleCollectedErrors & nsICertOverrideService::ERROR_UNTRUSTED) { params[0] = host.get(); const char *errorID = nsnull; nsCOMPtr<nsIX509Cert3> cert3 = do_QueryInterface(ix509); if (cert3) { Loading Loading @@ -728,7 +690,7 @@ getInvalidCertErrorMessage(PRUint32 multipleCollectedErrors, } nsString formattedString; rv = component->GetPIPNSSBundleString(errorID, nsresult rv = component->GetPIPNSSBundleString(errorID, formattedString); if (NS_SUCCEEDED(rv)) { Loading @@ -737,46 +699,39 @@ getInvalidCertErrorMessage(PRUint32 multipleCollectedErrors, } } if (multipleCollectedErrors & nsICertOverrideService::ERROR_MISMATCH) // returns TRUE if SAN was used to produce names // return FALSE if nothing was produced // names => a single name or a list of names // multipleNames => whether multiple names were delivered static PRBool GetSubjectAltNames(CERTCertificate *nssCert, nsINSSComponent *component, nsString &allNames, PRBool &multipleNames) { PRBool useSAN = PR_TRUE; // subject alt name extension PRBool multipleNames = PR_FALSE; nsString allNames; CERTCertificate *nssCert = NULL; CERTCertificateCleaner nssCertCleaner(nssCert); nsCOMPtr<nsIX509Cert2> cert2 = do_QueryInterface(ix509, &rv); if (cert2) nssCert = cert2->GetCert(); if (!nssCert) useSAN = PR_FALSE; allNames.Truncate(); multipleNames = PR_FALSE; PRArenaPool *san_arena = nsnull; SECItem altNameExtension = {siBuffer, NULL, 0 }; CERTGeneralName *sanNameList = nsnull; if (useSAN) { nsresult rv; rv = CERT_FindCertExtension(nssCert, SEC_OID_X509_SUBJECT_ALT_NAME, &altNameExtension); if (rv != SECSuccess) useSAN = PR_FALSE; } return PR_FALSE; if (useSAN) { san_arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (!san_arena) useSAN = PR_FALSE; } return PR_FALSE; if (useSAN) { sanNameList = CERT_DecodeAltNameExtension(san_arena, &altNameExtension); if (!sanNameList) useSAN = PR_FALSE; } return PR_FALSE; SECITEM_FreeItem(&altNameExtension, PR_FALSE); if (useSAN) { CERTGeneralName *current = sanNameList; do { nsAutoString name; Loading Loading @@ -822,19 +777,61 @@ getInvalidCertErrorMessage(PRUint32 multipleCollectedErrors, } current = CERT_GetNextGeneralName(current); } while (current != sanNameList); // double linked } if (san_arena) PORT_FreeArena(san_arena, PR_FALSE); return PR_TRUE; } static void AppendErrorTextMismatch(const nsString &host, nsIX509Cert* ix509, nsINSSComponent *component, nsString &returnedMessage) { const PRUnichar *params[1]; nsresult rv; CERTCertificate *nssCert = NULL; CERTCertificateCleaner nssCertCleaner(nssCert); nsCOMPtr<nsIX509Cert2> cert2 = do_QueryInterface(ix509, &rv); if (cert2) nssCert = cert2->GetCert(); if (!nssCert) { // We are unable to extract the valid names, say "not valid for name". params[0] = host.get(); nsString formattedString; rv = component->PIPBundleFormatStringFromName("certErrorMismatch", params, 1, formattedString); if (NS_SUCCEEDED(rv)) { returnedMessage.Append(formattedString); returnedMessage.Append(NS_LITERAL_STRING("\n")); } return; } nsString allNames; PRBool multipleNames = PR_FALSE; PRBool useSAN = PR_FALSE; if (nssCert) useSAN = GetSubjectAltNames(nssCert, component, allNames, multipleNames); if (!useSAN) { char *certName = nsnull; // currently CERT_FindNSStringExtension is not being exported by NSS. // If it gets exported, enable the following line. // certName = CERT_FindNSStringExtension(nssCert, SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME); if (!certName) { // However, it has been discussed to treat the extension as obsolete and ignore it. if (!certName) certName = CERT_GetCommonName(&nssCert->subject); } if (certName) { allNames.AssignASCII(certName); PORT_Free(certName); } } if (multipleNames) { nsString message; Loading @@ -848,6 +845,7 @@ getInvalidCertErrorMessage(PRUint32 multipleCollectedErrors, } } else { // !multipleNames const PRUnichar *params[1]; params[0] = allNames.get(); nsString formattedString; Loading @@ -861,45 +859,63 @@ getInvalidCertErrorMessage(PRUint32 multipleCollectedErrors, } } if (multipleCollectedErrors & nsICertOverrideService::ERROR_TIME) static void GetDateBoundary(nsIX509Cert* ix509, nsString &formattedDate, PRBool trueExpired_falseNotYetValid) { PRTime now = PR_Now(); trueExpired_falseNotYetValid = PR_TRUE; formattedDate.Truncate(); PRTime notAfter, notBefore, timeToUse; nsCOMPtr<nsIX509CertValidity> validity; const char *key; nsresult rv; rv = ix509->GetValidity(getter_AddRefs(validity)); if (NS_FAILED(rv)) return rv; return; rv = validity->GetNotAfter(¬After); if (NS_FAILED(rv)) return rv; return; rv = validity->GetNotBefore(¬Before); if (NS_FAILED(rv)) return rv; return; if (LL_CMP(now, >, notAfter)) { key = "certErrorExpired"; if (LL_CMP(PR_Now(), >, notAfter)) { timeToUse = notAfter; } else { key = "certErrorNotYetValid"; timeToUse = notBefore; trueExpired_falseNotYetValid = PR_FALSE; } nsAutoString formattedDate; nsIDateTimeFormat* aDateTimeFormat; rv = CallCreateInstance(NS_DATETIMEFORMAT_CONTRACTID, &aDateTimeFormat); if (NS_FAILED(rv)) return rv; return; aDateTimeFormat->FormatPRTime(nsnull, kDateFormatShort, kTimeFormatNoSeconds, timeToUse, formattedDate); NS_IF_RELEASE(aDateTimeFormat); params[0] = formattedDate.get(); } static void AppendErrorTextTime(nsIX509Cert* ix509, nsINSSComponent *component, nsString &returnedMessage) { nsAutoString formattedDate; PRBool trueExpired_falseNotYetValid; GetDateBoundary(ix509, formattedDate, trueExpired_falseNotYetValid); const PRUnichar *params[1]; params[0] = formattedDate.get(); // might be empty, if helper function had a problem const char *key = trueExpired_falseNotYetValid ? "certErrorExpired" : "certErrorNotYetValid"; nsresult rv; nsString formattedString; rv = component->PIPBundleFormatStringFromName(key, params, 1, formattedString); Loading @@ -910,6 +926,11 @@ getInvalidCertErrorMessage(PRUint32 multipleCollectedErrors, } } static void AppendErrorTextCode(PRErrorCode errorCodeToReport, nsINSSComponent *component, nsString &returnedMessage) { const char *codeName = nsNSSErrors::getDefaultErrorStringName(errorCodeToReport); if (codeName) { Loading @@ -917,9 +938,11 @@ getInvalidCertErrorMessage(PRUint32 multipleCollectedErrors, ToLowerCase(error_id); NS_ConvertASCIItoUTF16 idU(error_id); const PRUnichar *params[1]; params[0] = idU.get(); nsString formattedString; nsresult rv; rv = component->PIPBundleFormatStringFromName("certErrorCodePrefix", params, 1, formattedString); Loading @@ -934,6 +957,66 @@ getInvalidCertErrorMessage(PRUint32 multipleCollectedErrors, returnedMessage.Append(NS_LITERAL_STRING(")")); } } } static nsresult getInvalidCertErrorMessage(PRUint32 multipleCollectedErrors, PRErrorCode errorCodeToReport, PRErrorCode errTrust, PRErrorCode errMismatch, PRErrorCode errExpired, const nsString &host, const nsString &hostWithPort, PRInt32 port, nsIX509Cert* ix509, PRBool externalErrorReporting, nsINSSComponent *component, nsString &returnedMessage) { NS_ENSURE_ARG_POINTER(component); const PRUnichar *params[1]; nsresult rv; // 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\n")); } if (multipleCollectedErrors & nsICertOverrideService::ERROR_UNTRUSTED) { AppendErrorTextUntrusted(errTrust, host, ix509, component, returnedMessage); } if (multipleCollectedErrors & nsICertOverrideService::ERROR_MISMATCH) { AppendErrorTextMismatch(host, ix509, component, returnedMessage); } if (multipleCollectedErrors & nsICertOverrideService::ERROR_TIME) { AppendErrorTextTime(ix509, component, returnedMessage); } AppendErrorTextCode(errorCodeToReport, component, returnedMessage); return NS_OK; } Loading Loading
security/manager/ssl/src/nsNSSIOLayer.cpp +309 −226 Original line number Diff line number Diff line Loading @@ -651,51 +651,13 @@ getErrorMessage(PRInt32 err, return NS_OK; } static nsresult getInvalidCertErrorMessage(PRUint32 multipleCollectedErrors, PRErrorCode errorCodeToReport, PRErrorCode errTrust, PRErrorCode errMismatch, PRErrorCode errExpired, static void AppendErrorTextUntrusted(PRErrorCode errTrust, const nsString &host, const nsString &hostWithPort, PRInt32 port, nsIX509Cert* ix509, PRBool externalErrorReporting, nsINSSComponent *component, nsString &returnedMessage) { NS_ENSURE_ARG_POINTER(component); const PRUnichar *params[1]; nsresult rv; // 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\n")); } if (multipleCollectedErrors & nsICertOverrideService::ERROR_UNTRUSTED) { params[0] = host.get(); const char *errorID = nsnull; nsCOMPtr<nsIX509Cert3> cert3 = do_QueryInterface(ix509); if (cert3) { Loading Loading @@ -728,7 +690,7 @@ getInvalidCertErrorMessage(PRUint32 multipleCollectedErrors, } nsString formattedString; rv = component->GetPIPNSSBundleString(errorID, nsresult rv = component->GetPIPNSSBundleString(errorID, formattedString); if (NS_SUCCEEDED(rv)) { Loading @@ -737,46 +699,39 @@ getInvalidCertErrorMessage(PRUint32 multipleCollectedErrors, } } if (multipleCollectedErrors & nsICertOverrideService::ERROR_MISMATCH) // returns TRUE if SAN was used to produce names // return FALSE if nothing was produced // names => a single name or a list of names // multipleNames => whether multiple names were delivered static PRBool GetSubjectAltNames(CERTCertificate *nssCert, nsINSSComponent *component, nsString &allNames, PRBool &multipleNames) { PRBool useSAN = PR_TRUE; // subject alt name extension PRBool multipleNames = PR_FALSE; nsString allNames; CERTCertificate *nssCert = NULL; CERTCertificateCleaner nssCertCleaner(nssCert); nsCOMPtr<nsIX509Cert2> cert2 = do_QueryInterface(ix509, &rv); if (cert2) nssCert = cert2->GetCert(); if (!nssCert) useSAN = PR_FALSE; allNames.Truncate(); multipleNames = PR_FALSE; PRArenaPool *san_arena = nsnull; SECItem altNameExtension = {siBuffer, NULL, 0 }; CERTGeneralName *sanNameList = nsnull; if (useSAN) { nsresult rv; rv = CERT_FindCertExtension(nssCert, SEC_OID_X509_SUBJECT_ALT_NAME, &altNameExtension); if (rv != SECSuccess) useSAN = PR_FALSE; } return PR_FALSE; if (useSAN) { san_arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (!san_arena) useSAN = PR_FALSE; } return PR_FALSE; if (useSAN) { sanNameList = CERT_DecodeAltNameExtension(san_arena, &altNameExtension); if (!sanNameList) useSAN = PR_FALSE; } return PR_FALSE; SECITEM_FreeItem(&altNameExtension, PR_FALSE); if (useSAN) { CERTGeneralName *current = sanNameList; do { nsAutoString name; Loading Loading @@ -822,19 +777,61 @@ getInvalidCertErrorMessage(PRUint32 multipleCollectedErrors, } current = CERT_GetNextGeneralName(current); } while (current != sanNameList); // double linked } if (san_arena) PORT_FreeArena(san_arena, PR_FALSE); return PR_TRUE; } static void AppendErrorTextMismatch(const nsString &host, nsIX509Cert* ix509, nsINSSComponent *component, nsString &returnedMessage) { const PRUnichar *params[1]; nsresult rv; CERTCertificate *nssCert = NULL; CERTCertificateCleaner nssCertCleaner(nssCert); nsCOMPtr<nsIX509Cert2> cert2 = do_QueryInterface(ix509, &rv); if (cert2) nssCert = cert2->GetCert(); if (!nssCert) { // We are unable to extract the valid names, say "not valid for name". params[0] = host.get(); nsString formattedString; rv = component->PIPBundleFormatStringFromName("certErrorMismatch", params, 1, formattedString); if (NS_SUCCEEDED(rv)) { returnedMessage.Append(formattedString); returnedMessage.Append(NS_LITERAL_STRING("\n")); } return; } nsString allNames; PRBool multipleNames = PR_FALSE; PRBool useSAN = PR_FALSE; if (nssCert) useSAN = GetSubjectAltNames(nssCert, component, allNames, multipleNames); if (!useSAN) { char *certName = nsnull; // currently CERT_FindNSStringExtension is not being exported by NSS. // If it gets exported, enable the following line. // certName = CERT_FindNSStringExtension(nssCert, SEC_OID_NS_CERT_EXT_SSL_SERVER_NAME); if (!certName) { // However, it has been discussed to treat the extension as obsolete and ignore it. if (!certName) certName = CERT_GetCommonName(&nssCert->subject); } if (certName) { allNames.AssignASCII(certName); PORT_Free(certName); } } if (multipleNames) { nsString message; Loading @@ -848,6 +845,7 @@ getInvalidCertErrorMessage(PRUint32 multipleCollectedErrors, } } else { // !multipleNames const PRUnichar *params[1]; params[0] = allNames.get(); nsString formattedString; Loading @@ -861,45 +859,63 @@ getInvalidCertErrorMessage(PRUint32 multipleCollectedErrors, } } if (multipleCollectedErrors & nsICertOverrideService::ERROR_TIME) static void GetDateBoundary(nsIX509Cert* ix509, nsString &formattedDate, PRBool trueExpired_falseNotYetValid) { PRTime now = PR_Now(); trueExpired_falseNotYetValid = PR_TRUE; formattedDate.Truncate(); PRTime notAfter, notBefore, timeToUse; nsCOMPtr<nsIX509CertValidity> validity; const char *key; nsresult rv; rv = ix509->GetValidity(getter_AddRefs(validity)); if (NS_FAILED(rv)) return rv; return; rv = validity->GetNotAfter(¬After); if (NS_FAILED(rv)) return rv; return; rv = validity->GetNotBefore(¬Before); if (NS_FAILED(rv)) return rv; return; if (LL_CMP(now, >, notAfter)) { key = "certErrorExpired"; if (LL_CMP(PR_Now(), >, notAfter)) { timeToUse = notAfter; } else { key = "certErrorNotYetValid"; timeToUse = notBefore; trueExpired_falseNotYetValid = PR_FALSE; } nsAutoString formattedDate; nsIDateTimeFormat* aDateTimeFormat; rv = CallCreateInstance(NS_DATETIMEFORMAT_CONTRACTID, &aDateTimeFormat); if (NS_FAILED(rv)) return rv; return; aDateTimeFormat->FormatPRTime(nsnull, kDateFormatShort, kTimeFormatNoSeconds, timeToUse, formattedDate); NS_IF_RELEASE(aDateTimeFormat); params[0] = formattedDate.get(); } static void AppendErrorTextTime(nsIX509Cert* ix509, nsINSSComponent *component, nsString &returnedMessage) { nsAutoString formattedDate; PRBool trueExpired_falseNotYetValid; GetDateBoundary(ix509, formattedDate, trueExpired_falseNotYetValid); const PRUnichar *params[1]; params[0] = formattedDate.get(); // might be empty, if helper function had a problem const char *key = trueExpired_falseNotYetValid ? "certErrorExpired" : "certErrorNotYetValid"; nsresult rv; nsString formattedString; rv = component->PIPBundleFormatStringFromName(key, params, 1, formattedString); Loading @@ -910,6 +926,11 @@ getInvalidCertErrorMessage(PRUint32 multipleCollectedErrors, } } static void AppendErrorTextCode(PRErrorCode errorCodeToReport, nsINSSComponent *component, nsString &returnedMessage) { const char *codeName = nsNSSErrors::getDefaultErrorStringName(errorCodeToReport); if (codeName) { Loading @@ -917,9 +938,11 @@ getInvalidCertErrorMessage(PRUint32 multipleCollectedErrors, ToLowerCase(error_id); NS_ConvertASCIItoUTF16 idU(error_id); const PRUnichar *params[1]; params[0] = idU.get(); nsString formattedString; nsresult rv; rv = component->PIPBundleFormatStringFromName("certErrorCodePrefix", params, 1, formattedString); Loading @@ -934,6 +957,66 @@ getInvalidCertErrorMessage(PRUint32 multipleCollectedErrors, returnedMessage.Append(NS_LITERAL_STRING(")")); } } } static nsresult getInvalidCertErrorMessage(PRUint32 multipleCollectedErrors, PRErrorCode errorCodeToReport, PRErrorCode errTrust, PRErrorCode errMismatch, PRErrorCode errExpired, const nsString &host, const nsString &hostWithPort, PRInt32 port, nsIX509Cert* ix509, PRBool externalErrorReporting, nsINSSComponent *component, nsString &returnedMessage) { NS_ENSURE_ARG_POINTER(component); const PRUnichar *params[1]; nsresult rv; // 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\n")); } if (multipleCollectedErrors & nsICertOverrideService::ERROR_UNTRUSTED) { AppendErrorTextUntrusted(errTrust, host, ix509, component, returnedMessage); } if (multipleCollectedErrors & nsICertOverrideService::ERROR_MISMATCH) { AppendErrorTextMismatch(host, ix509, component, returnedMessage); } if (multipleCollectedErrors & nsICertOverrideService::ERROR_TIME) { AppendErrorTextTime(ix509, component, returnedMessage); } AppendErrorTextCode(errorCodeToReport, component, returnedMessage); return NS_OK; } Loading