Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nsRecentBadCerts.h"
9 #include "pkix/pkixtypes.h"
10 #include "nsIX509Cert.h"
11 #include "nsIObserverService.h"
12 #include "mozilla/RefPtr.h"
13 #include "mozilla/Services.h"
14 #include "nsSSLStatus.h"
15 #include "nsCOMPtr.h"
16 #include "nsNSSCertificate.h"
17 #include "nsCRT.h"
18 #include "nsPromiseFlatString.h"
19 #include "nsStringBuffer.h"
20 #include "nspr.h"
21 #include "pk11pub.h"
22 #include "certdb.h"
23 #include "sechash.h"
25 using namespace mozilla;
27 NS_IMPL_ISUPPORTS(nsRecentBadCerts, nsIRecentBadCerts)
29 nsRecentBadCerts::nsRecentBadCerts()
30 :monitor("nsRecentBadCerts.monitor")
31 ,mNextStorePosition(0)
32 {
33 }
35 nsRecentBadCerts::~nsRecentBadCerts()
36 {
37 }
39 NS_IMETHODIMP
40 nsRecentBadCerts::GetRecentBadCert(const nsAString & aHostNameWithPort,
41 nsISSLStatus **aStatus)
42 {
43 NS_ENSURE_ARG_POINTER(aStatus);
44 if (!aHostNameWithPort.Length())
45 return NS_ERROR_INVALID_ARG;
47 *aStatus = nullptr;
48 RefPtr<nsSSLStatus> status(new nsSSLStatus());
50 SECItem foundDER;
51 foundDER.len = 0;
52 foundDER.data = nullptr;
54 bool isDomainMismatch = false;
55 bool isNotValidAtThisTime = false;
56 bool isUntrusted = false;
58 {
59 ReentrantMonitorAutoEnter lock(monitor);
60 for (size_t i=0; i<const_recently_seen_list_size; ++i) {
61 if (mCerts[i].mHostWithPort.Equals(aHostNameWithPort)) {
62 SECStatus srv = SECITEM_CopyItem(nullptr, &foundDER, &mCerts[i].mDERCert);
63 if (srv != SECSuccess)
64 return NS_ERROR_OUT_OF_MEMORY;
66 isDomainMismatch = mCerts[i].isDomainMismatch;
67 isNotValidAtThisTime = mCerts[i].isNotValidAtThisTime;
68 isUntrusted = mCerts[i].isUntrusted;
69 }
70 }
71 }
73 if (foundDER.len) {
74 CERTCertDBHandle *certdb = CERT_GetDefaultCertDB();
75 mozilla::pkix::ScopedCERTCertificate nssCert(
76 CERT_FindCertByDERCert(certdb, &foundDER));
77 if (!nssCert)
78 nssCert = CERT_NewTempCertificate(certdb, &foundDER,
79 nullptr, // no nickname
80 false, // not perm
81 true); // copy der
83 SECITEM_FreeItem(&foundDER, false);
85 if (!nssCert)
86 return NS_ERROR_FAILURE;
88 status->mServerCert = nsNSSCertificate::Create(nssCert.get());
89 status->mHaveCertErrorBits = true;
90 status->mIsDomainMismatch = isDomainMismatch;
91 status->mIsNotValidAtThisTime = isNotValidAtThisTime;
92 status->mIsUntrusted = isUntrusted;
94 *aStatus = status;
95 NS_IF_ADDREF(*aStatus);
96 }
98 return NS_OK;
99 }
101 NS_IMETHODIMP
102 nsRecentBadCerts::AddBadCert(const nsAString &hostWithPort,
103 nsISSLStatus *aStatus)
104 {
105 NS_ENSURE_ARG(aStatus);
107 nsCOMPtr<nsIX509Cert> cert;
108 nsresult rv;
109 rv = aStatus->GetServerCert(getter_AddRefs(cert));
110 NS_ENSURE_SUCCESS(rv, rv);
112 bool isDomainMismatch;
113 bool isNotValidAtThisTime;
114 bool isUntrusted;
116 rv = aStatus->GetIsDomainMismatch(&isDomainMismatch);
117 NS_ENSURE_SUCCESS(rv, rv);
119 rv = aStatus->GetIsNotValidAtThisTime(&isNotValidAtThisTime);
120 NS_ENSURE_SUCCESS(rv, rv);
122 rv = aStatus->GetIsUntrusted(&isUntrusted);
123 NS_ENSURE_SUCCESS(rv, rv);
125 SECItem tempItem;
126 rv = cert->GetRawDER(&tempItem.len, (uint8_t **)&tempItem.data);
127 NS_ENSURE_SUCCESS(rv, rv);
129 {
130 ReentrantMonitorAutoEnter lock(monitor);
131 RecentBadCert &updatedEntry = mCerts[mNextStorePosition];
133 ++mNextStorePosition;
134 if (mNextStorePosition == const_recently_seen_list_size)
135 mNextStorePosition = 0;
137 updatedEntry.Clear();
138 updatedEntry.mHostWithPort = hostWithPort;
139 updatedEntry.mDERCert = tempItem; // consume
140 updatedEntry.isDomainMismatch = isDomainMismatch;
141 updatedEntry.isNotValidAtThisTime = isNotValidAtThisTime;
142 updatedEntry.isUntrusted = isUntrusted;
143 }
145 return NS_OK;
146 }
148 NS_IMETHODIMP
149 nsRecentBadCerts::ResetStoredCerts()
150 {
151 for (size_t i = 0; i < const_recently_seen_list_size; ++i) {
152 RecentBadCert &entry = mCerts[i];
153 entry.Clear();
154 }
155 return NS_OK;
156 }