1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 : *
3 : * ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is mozilla.org code.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Red Hat, Inc.
20 : * Portions created by the Initial Developer are Copyright (C) 2006
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : * Kai Engert <kengert@redhat.com>
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either the GNU General Public License Version 2 or later (the "GPL"), or
28 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : #include "nsRecentBadCerts.h"
41 : #include "nsIX509Cert.h"
42 : #include "nsSSLStatus.h"
43 : #include "nsCOMPtr.h"
44 : #include "nsAutoPtr.h"
45 : #include "nsNSSCertificate.h"
46 : #include "nsCRT.h"
47 : #include "nsPromiseFlatString.h"
48 : #include "nsStringBuffer.h"
49 : #include "nsAutoPtr.h"
50 : #include "nspr.h"
51 : #include "pk11pub.h"
52 : #include "certdb.h"
53 : #include "sechash.h"
54 :
55 : #include "nsNSSCleaner.h"
56 :
57 : using namespace mozilla;
58 :
59 : NSSCleanupAutoPtrClass(CERTCertificate, CERT_DestroyCertificate)
60 :
61 0 : NS_IMPL_THREADSAFE_ISUPPORTS1(nsRecentBadCertsService,
62 : nsIRecentBadCertsService)
63 :
64 0 : nsRecentBadCertsService::nsRecentBadCertsService()
65 : :monitor("nsRecentBadCertsService.monitor")
66 0 : ,mNextStorePosition(0)
67 : {
68 0 : }
69 :
70 0 : nsRecentBadCertsService::~nsRecentBadCertsService()
71 : {
72 0 : }
73 :
74 : nsresult
75 0 : nsRecentBadCertsService::Init()
76 : {
77 0 : return NS_OK;
78 : }
79 :
80 : NS_IMETHODIMP
81 0 : nsRecentBadCertsService::GetRecentBadCert(const nsAString & aHostNameWithPort,
82 : nsISSLStatus **aStatus)
83 : {
84 0 : NS_ENSURE_ARG_POINTER(aStatus);
85 0 : if (!aHostNameWithPort.Length())
86 0 : return NS_ERROR_INVALID_ARG;
87 :
88 0 : *aStatus = nsnull;
89 0 : nsRefPtr<nsSSLStatus> status = new nsSSLStatus();
90 0 : if (!status)
91 0 : return NS_ERROR_OUT_OF_MEMORY;
92 :
93 : SECItem foundDER;
94 0 : foundDER.len = 0;
95 0 : foundDER.data = nsnull;
96 :
97 0 : bool isDomainMismatch = false;
98 0 : bool isNotValidAtThisTime = false;
99 0 : bool isUntrusted = false;
100 :
101 : {
102 0 : ReentrantMonitorAutoEnter lock(monitor);
103 0 : for (size_t i=0; i<const_recently_seen_list_size; ++i) {
104 0 : if (mCerts[i].mHostWithPort.Equals(aHostNameWithPort)) {
105 0 : SECStatus srv = SECITEM_CopyItem(nsnull, &foundDER, &mCerts[i].mDERCert);
106 0 : if (srv != SECSuccess)
107 0 : return NS_ERROR_OUT_OF_MEMORY;
108 :
109 0 : isDomainMismatch = mCerts[i].isDomainMismatch;
110 0 : isNotValidAtThisTime = mCerts[i].isNotValidAtThisTime;
111 0 : isUntrusted = mCerts[i].isUntrusted;
112 : }
113 : }
114 : }
115 :
116 0 : if (foundDER.len) {
117 : CERTCertificate *nssCert;
118 0 : CERTCertDBHandle *certdb = CERT_GetDefaultCertDB();
119 0 : nssCert = CERT_FindCertByDERCert(certdb, &foundDER);
120 0 : if (!nssCert)
121 : nssCert = CERT_NewTempCertificate(certdb, &foundDER,
122 : nsnull, // no nickname
123 : false, // not perm
124 0 : true); // copy der
125 :
126 0 : SECITEM_FreeItem(&foundDER, false);
127 :
128 0 : if (!nssCert)
129 0 : return NS_ERROR_FAILURE;
130 :
131 0 : status->mServerCert = nsNSSCertificate::Create(nssCert);
132 0 : CERT_DestroyCertificate(nssCert);
133 :
134 0 : status->mHaveCertErrorBits = true;
135 0 : status->mIsDomainMismatch = isDomainMismatch;
136 0 : status->mIsNotValidAtThisTime = isNotValidAtThisTime;
137 0 : status->mIsUntrusted = isUntrusted;
138 :
139 0 : *aStatus = status;
140 0 : NS_IF_ADDREF(*aStatus);
141 : }
142 :
143 0 : return NS_OK;
144 : }
145 :
146 : NS_IMETHODIMP
147 0 : nsRecentBadCertsService::AddBadCert(const nsAString &hostWithPort,
148 : nsISSLStatus *aStatus)
149 : {
150 0 : NS_ENSURE_ARG(aStatus);
151 :
152 0 : nsCOMPtr<nsIX509Cert> cert;
153 : nsresult rv;
154 0 : rv = aStatus->GetServerCert(getter_AddRefs(cert));
155 0 : NS_ENSURE_SUCCESS(rv, rv);
156 :
157 : bool isDomainMismatch;
158 : bool isNotValidAtThisTime;
159 : bool isUntrusted;
160 :
161 0 : rv = aStatus->GetIsDomainMismatch(&isDomainMismatch);
162 0 : NS_ENSURE_SUCCESS(rv, rv);
163 :
164 0 : rv = aStatus->GetIsNotValidAtThisTime(&isNotValidAtThisTime);
165 0 : NS_ENSURE_SUCCESS(rv, rv);
166 :
167 0 : rv = aStatus->GetIsUntrusted(&isUntrusted);
168 0 : NS_ENSURE_SUCCESS(rv, rv);
169 :
170 : SECItem tempItem;
171 0 : rv = cert->GetRawDER(&tempItem.len, (PRUint8 **)&tempItem.data);
172 0 : NS_ENSURE_SUCCESS(rv, rv);
173 :
174 : {
175 0 : ReentrantMonitorAutoEnter lock(monitor);
176 0 : RecentBadCert &updatedEntry = mCerts[mNextStorePosition];
177 :
178 0 : ++mNextStorePosition;
179 0 : if (mNextStorePosition == const_recently_seen_list_size)
180 0 : mNextStorePosition = 0;
181 :
182 0 : updatedEntry.Clear();
183 0 : updatedEntry.mHostWithPort = hostWithPort;
184 0 : updatedEntry.mDERCert = tempItem; // consume
185 0 : updatedEntry.isDomainMismatch = isDomainMismatch;
186 0 : updatedEntry.isNotValidAtThisTime = isNotValidAtThisTime;
187 0 : updatedEntry.isUntrusted = isUntrusted;
188 : }
189 :
190 0 : return NS_OK;
191 : }
|