1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/manager/ssl/src/nsRecentBadCerts.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,156 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * 1.6 + * This Source Code Form is subject to the terms of the Mozilla Public 1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.9 + 1.10 +#include "nsRecentBadCerts.h" 1.11 + 1.12 +#include "pkix/pkixtypes.h" 1.13 +#include "nsIX509Cert.h" 1.14 +#include "nsIObserverService.h" 1.15 +#include "mozilla/RefPtr.h" 1.16 +#include "mozilla/Services.h" 1.17 +#include "nsSSLStatus.h" 1.18 +#include "nsCOMPtr.h" 1.19 +#include "nsNSSCertificate.h" 1.20 +#include "nsCRT.h" 1.21 +#include "nsPromiseFlatString.h" 1.22 +#include "nsStringBuffer.h" 1.23 +#include "nspr.h" 1.24 +#include "pk11pub.h" 1.25 +#include "certdb.h" 1.26 +#include "sechash.h" 1.27 + 1.28 +using namespace mozilla; 1.29 + 1.30 +NS_IMPL_ISUPPORTS(nsRecentBadCerts, nsIRecentBadCerts) 1.31 + 1.32 +nsRecentBadCerts::nsRecentBadCerts() 1.33 +:monitor("nsRecentBadCerts.monitor") 1.34 +,mNextStorePosition(0) 1.35 +{ 1.36 +} 1.37 + 1.38 +nsRecentBadCerts::~nsRecentBadCerts() 1.39 +{ 1.40 +} 1.41 + 1.42 +NS_IMETHODIMP 1.43 +nsRecentBadCerts::GetRecentBadCert(const nsAString & aHostNameWithPort, 1.44 + nsISSLStatus **aStatus) 1.45 +{ 1.46 + NS_ENSURE_ARG_POINTER(aStatus); 1.47 + if (!aHostNameWithPort.Length()) 1.48 + return NS_ERROR_INVALID_ARG; 1.49 + 1.50 + *aStatus = nullptr; 1.51 + RefPtr<nsSSLStatus> status(new nsSSLStatus()); 1.52 + 1.53 + SECItem foundDER; 1.54 + foundDER.len = 0; 1.55 + foundDER.data = nullptr; 1.56 + 1.57 + bool isDomainMismatch = false; 1.58 + bool isNotValidAtThisTime = false; 1.59 + bool isUntrusted = false; 1.60 + 1.61 + { 1.62 + ReentrantMonitorAutoEnter lock(monitor); 1.63 + for (size_t i=0; i<const_recently_seen_list_size; ++i) { 1.64 + if (mCerts[i].mHostWithPort.Equals(aHostNameWithPort)) { 1.65 + SECStatus srv = SECITEM_CopyItem(nullptr, &foundDER, &mCerts[i].mDERCert); 1.66 + if (srv != SECSuccess) 1.67 + return NS_ERROR_OUT_OF_MEMORY; 1.68 + 1.69 + isDomainMismatch = mCerts[i].isDomainMismatch; 1.70 + isNotValidAtThisTime = mCerts[i].isNotValidAtThisTime; 1.71 + isUntrusted = mCerts[i].isUntrusted; 1.72 + } 1.73 + } 1.74 + } 1.75 + 1.76 + if (foundDER.len) { 1.77 + CERTCertDBHandle *certdb = CERT_GetDefaultCertDB(); 1.78 + mozilla::pkix::ScopedCERTCertificate nssCert( 1.79 + CERT_FindCertByDERCert(certdb, &foundDER)); 1.80 + if (!nssCert) 1.81 + nssCert = CERT_NewTempCertificate(certdb, &foundDER, 1.82 + nullptr, // no nickname 1.83 + false, // not perm 1.84 + true); // copy der 1.85 + 1.86 + SECITEM_FreeItem(&foundDER, false); 1.87 + 1.88 + if (!nssCert) 1.89 + return NS_ERROR_FAILURE; 1.90 + 1.91 + status->mServerCert = nsNSSCertificate::Create(nssCert.get()); 1.92 + status->mHaveCertErrorBits = true; 1.93 + status->mIsDomainMismatch = isDomainMismatch; 1.94 + status->mIsNotValidAtThisTime = isNotValidAtThisTime; 1.95 + status->mIsUntrusted = isUntrusted; 1.96 + 1.97 + *aStatus = status; 1.98 + NS_IF_ADDREF(*aStatus); 1.99 + } 1.100 + 1.101 + return NS_OK; 1.102 +} 1.103 + 1.104 +NS_IMETHODIMP 1.105 +nsRecentBadCerts::AddBadCert(const nsAString &hostWithPort, 1.106 + nsISSLStatus *aStatus) 1.107 +{ 1.108 + NS_ENSURE_ARG(aStatus); 1.109 + 1.110 + nsCOMPtr<nsIX509Cert> cert; 1.111 + nsresult rv; 1.112 + rv = aStatus->GetServerCert(getter_AddRefs(cert)); 1.113 + NS_ENSURE_SUCCESS(rv, rv); 1.114 + 1.115 + bool isDomainMismatch; 1.116 + bool isNotValidAtThisTime; 1.117 + bool isUntrusted; 1.118 + 1.119 + rv = aStatus->GetIsDomainMismatch(&isDomainMismatch); 1.120 + NS_ENSURE_SUCCESS(rv, rv); 1.121 + 1.122 + rv = aStatus->GetIsNotValidAtThisTime(&isNotValidAtThisTime); 1.123 + NS_ENSURE_SUCCESS(rv, rv); 1.124 + 1.125 + rv = aStatus->GetIsUntrusted(&isUntrusted); 1.126 + NS_ENSURE_SUCCESS(rv, rv); 1.127 + 1.128 + SECItem tempItem; 1.129 + rv = cert->GetRawDER(&tempItem.len, (uint8_t **)&tempItem.data); 1.130 + NS_ENSURE_SUCCESS(rv, rv); 1.131 + 1.132 + { 1.133 + ReentrantMonitorAutoEnter lock(monitor); 1.134 + RecentBadCert &updatedEntry = mCerts[mNextStorePosition]; 1.135 + 1.136 + ++mNextStorePosition; 1.137 + if (mNextStorePosition == const_recently_seen_list_size) 1.138 + mNextStorePosition = 0; 1.139 + 1.140 + updatedEntry.Clear(); 1.141 + updatedEntry.mHostWithPort = hostWithPort; 1.142 + updatedEntry.mDERCert = tempItem; // consume 1.143 + updatedEntry.isDomainMismatch = isDomainMismatch; 1.144 + updatedEntry.isNotValidAtThisTime = isNotValidAtThisTime; 1.145 + updatedEntry.isUntrusted = isUntrusted; 1.146 + } 1.147 + 1.148 + return NS_OK; 1.149 +} 1.150 + 1.151 +NS_IMETHODIMP 1.152 +nsRecentBadCerts::ResetStoredCerts() 1.153 +{ 1.154 + for (size_t i = 0; i < const_recently_seen_list_size; ++i) { 1.155 + RecentBadCert &entry = mCerts[i]; 1.156 + entry.Clear(); 1.157 + } 1.158 + return NS_OK; 1.159 +}