michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsRecentBadCerts.h" michael@0: michael@0: #include "pkix/pkixtypes.h" michael@0: #include "nsIX509Cert.h" michael@0: #include "nsIObserverService.h" michael@0: #include "mozilla/RefPtr.h" michael@0: #include "mozilla/Services.h" michael@0: #include "nsSSLStatus.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsNSSCertificate.h" michael@0: #include "nsCRT.h" michael@0: #include "nsPromiseFlatString.h" michael@0: #include "nsStringBuffer.h" michael@0: #include "nspr.h" michael@0: #include "pk11pub.h" michael@0: #include "certdb.h" michael@0: #include "sechash.h" michael@0: michael@0: using namespace mozilla; michael@0: michael@0: NS_IMPL_ISUPPORTS(nsRecentBadCerts, nsIRecentBadCerts) michael@0: michael@0: nsRecentBadCerts::nsRecentBadCerts() michael@0: :monitor("nsRecentBadCerts.monitor") michael@0: ,mNextStorePosition(0) michael@0: { michael@0: } michael@0: michael@0: nsRecentBadCerts::~nsRecentBadCerts() michael@0: { michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsRecentBadCerts::GetRecentBadCert(const nsAString & aHostNameWithPort, michael@0: nsISSLStatus **aStatus) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aStatus); michael@0: if (!aHostNameWithPort.Length()) michael@0: return NS_ERROR_INVALID_ARG; michael@0: michael@0: *aStatus = nullptr; michael@0: RefPtr status(new nsSSLStatus()); michael@0: michael@0: SECItem foundDER; michael@0: foundDER.len = 0; michael@0: foundDER.data = nullptr; michael@0: michael@0: bool isDomainMismatch = false; michael@0: bool isNotValidAtThisTime = false; michael@0: bool isUntrusted = false; michael@0: michael@0: { michael@0: ReentrantMonitorAutoEnter lock(monitor); michael@0: for (size_t i=0; imServerCert = nsNSSCertificate::Create(nssCert.get()); michael@0: status->mHaveCertErrorBits = true; michael@0: status->mIsDomainMismatch = isDomainMismatch; michael@0: status->mIsNotValidAtThisTime = isNotValidAtThisTime; michael@0: status->mIsUntrusted = isUntrusted; michael@0: michael@0: *aStatus = status; michael@0: NS_IF_ADDREF(*aStatus); michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsRecentBadCerts::AddBadCert(const nsAString &hostWithPort, michael@0: nsISSLStatus *aStatus) michael@0: { michael@0: NS_ENSURE_ARG(aStatus); michael@0: michael@0: nsCOMPtr cert; michael@0: nsresult rv; michael@0: rv = aStatus->GetServerCert(getter_AddRefs(cert)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: bool isDomainMismatch; michael@0: bool isNotValidAtThisTime; michael@0: bool isUntrusted; michael@0: michael@0: rv = aStatus->GetIsDomainMismatch(&isDomainMismatch); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: rv = aStatus->GetIsNotValidAtThisTime(&isNotValidAtThisTime); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: rv = aStatus->GetIsUntrusted(&isUntrusted); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: SECItem tempItem; michael@0: rv = cert->GetRawDER(&tempItem.len, (uint8_t **)&tempItem.data); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: { michael@0: ReentrantMonitorAutoEnter lock(monitor); michael@0: RecentBadCert &updatedEntry = mCerts[mNextStorePosition]; michael@0: michael@0: ++mNextStorePosition; michael@0: if (mNextStorePosition == const_recently_seen_list_size) michael@0: mNextStorePosition = 0; michael@0: michael@0: updatedEntry.Clear(); michael@0: updatedEntry.mHostWithPort = hostWithPort; michael@0: updatedEntry.mDERCert = tempItem; // consume michael@0: updatedEntry.isDomainMismatch = isDomainMismatch; michael@0: updatedEntry.isNotValidAtThisTime = isNotValidAtThisTime; michael@0: updatedEntry.isUntrusted = isUntrusted; michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsRecentBadCerts::ResetStoredCerts() michael@0: { michael@0: for (size_t i = 0; i < const_recently_seen_list_size; ++i) { michael@0: RecentBadCert &entry = mCerts[i]; michael@0: entry.Clear(); michael@0: } michael@0: return NS_OK; michael@0: }