Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(274)

Side by Side Diff: net/third_party/mozilla_security_manager/nsNSSCertificateDB.cpp

Issue 10458069: Reland: Fix imported server certs being distrusted in NSS 3.13. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix the test failures Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/third_party/mozilla_security_manager/nsNSSCertificateDB.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* ***** BEGIN LICENSE BLOCK ***** 1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3 * 3 *
4 * The contents of this file are subject to the Mozilla Public License Version 4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with 5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at 6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/ 7 * http://www.mozilla.org/MPL/
8 * 8 *
9 * Software distributed under the License is distributed on an "AS IS" basis, 9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License 10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
(...skipping 21 matching lines...) Expand all
32 * decision by deleting the provisions above and replace them with the notice 32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete 33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under 34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL. 35 * the terms of any one of the MPL, the GPL or the LGPL.
36 * 36 *
37 * ***** END LICENSE BLOCK ***** */ 37 * ***** END LICENSE BLOCK ***** */
38 38
39 #include "net/third_party/mozilla_security_manager/nsNSSCertificateDB.h" 39 #include "net/third_party/mozilla_security_manager/nsNSSCertificateDB.h"
40 40
41 #include <cert.h> 41 #include <cert.h>
42 #include <certdb.h>
42 #include <pk11pub.h> 43 #include <pk11pub.h>
43 #include <secerr.h> 44 #include <secerr.h>
44 45
45 #include "base/logging.h" 46 #include "base/logging.h"
46 #include "crypto/nss_util_internal.h" 47 #include "crypto/nss_util_internal.h"
47 #include "crypto/scoped_nss_types.h" 48 #include "crypto/scoped_nss_types.h"
48 #include "net/base/net_errors.h" 49 #include "net/base/net_errors.h"
49 #include "net/base/x509_certificate.h" 50 #include "net/base/x509_certificate.h"
50 #include "net/third_party/mozilla_security_manager/nsNSSCertTrust.h" 51
52 #if !defined(CERTDB_TERMINAL_RECORD)
53 /* NSS 3.13 renames CERTDB_VALID_PEER to CERTDB_TERMINAL_RECORD
54 * and marks CERTDB_VALID_PEER as deprecated.
55 * If we're using an older version, rename it ourselves.
56 */
57 #define CERTDB_TERMINAL_RECORD CERTDB_VALID_PEER
58 #endif
51 59
52 namespace mozilla_security_manager { 60 namespace mozilla_security_manager {
53 61
54 // Based on nsNSSCertificateDB::handleCACertDownload, minus the UI bits. 62 // Based on nsNSSCertificateDB::handleCACertDownload, minus the UI bits.
55 bool ImportCACerts(const net::CertificateList& certificates, 63 bool ImportCACerts(const net::CertificateList& certificates,
56 net::X509Certificate* root, 64 net::X509Certificate* root,
57 net::CertDatabase::TrustBits trustBits, 65 net::CertDatabase::TrustBits trustBits,
58 net::CertDatabase::ImportCertFailureList* not_imported) { 66 net::CertDatabase::ImportCertFailureList* not_imported) {
67 if (certificates.empty() || !root)
68 return false;
69
59 crypto::ScopedPK11Slot slot(crypto::GetPublicNSSKeySlot()); 70 crypto::ScopedPK11Slot slot(crypto::GetPublicNSSKeySlot());
60 if (!slot.get()) { 71 if (!slot.get()) {
61 LOG(ERROR) << "Couldn't get internal key slot!"; 72 LOG(ERROR) << "Couldn't get internal key slot!";
62 return false; 73 return false;
63 } 74 }
64 75
65 // Mozilla had some code here to check if a perm version of the cert exists 76 // Mozilla had some code here to check if a perm version of the cert exists
66 // already and use that, but CERT_NewTempCertificate actually does that 77 // already and use that, but CERT_NewTempCertificate actually does that
67 // itself, so we skip it here. 78 // itself, so we skip it here.
68 79
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 cert, net::ERR_IMPORT_CA_CERT_FAILED)); 162 cert, net::ERR_IMPORT_CA_CERT_FAILED));
152 } 163 }
153 } 164 }
154 165
155 // Any errors importing individual certs will be in listed in |not_imported|. 166 // Any errors importing individual certs will be in listed in |not_imported|.
156 return true; 167 return true;
157 } 168 }
158 169
159 // Based on nsNSSCertificateDB::ImportServerCertificate. 170 // Based on nsNSSCertificateDB::ImportServerCertificate.
160 bool ImportServerCert(const net::CertificateList& certificates, 171 bool ImportServerCert(const net::CertificateList& certificates,
172 net::CertDatabase::TrustBits trustBits,
161 net::CertDatabase::ImportCertFailureList* not_imported) { 173 net::CertDatabase::ImportCertFailureList* not_imported) {
174 if (certificates.empty())
175 return false;
176
162 crypto::ScopedPK11Slot slot(crypto::GetPublicNSSKeySlot()); 177 crypto::ScopedPK11Slot slot(crypto::GetPublicNSSKeySlot());
163 if (!slot.get()) { 178 if (!slot.get()) {
164 LOG(ERROR) << "Couldn't get internal key slot!"; 179 LOG(ERROR) << "Couldn't get internal key slot!";
165 return false; 180 return false;
166 } 181 }
167 182
168 for (size_t i = 0; i < certificates.size(); ++i) { 183 for (size_t i = 0; i < certificates.size(); ++i) {
169 const scoped_refptr<net::X509Certificate>& cert = certificates[i]; 184 const scoped_refptr<net::X509Certificate>& cert = certificates[i];
170 185
171 // Mozilla uses CERT_ImportCerts, which doesn't take a slot arg. We use 186 // Mozilla uses CERT_ImportCerts, which doesn't take a slot arg. We use
172 // PK11_ImportCert instead. 187 // PK11_ImportCert instead.
173 SECStatus srv = PK11_ImportCert( 188 SECStatus srv = PK11_ImportCert(
174 slot.get(), 189 slot.get(),
175 cert->os_cert_handle(), 190 cert->os_cert_handle(),
176 CK_INVALID_HANDLE, 191 CK_INVALID_HANDLE,
177 cert->GetDefaultNickname(net::SERVER_CERT).c_str(), 192 cert->GetDefaultNickname(net::SERVER_CERT).c_str(),
178 PR_FALSE /* includeTrust (unused) */); 193 PR_FALSE /* includeTrust (unused) */);
179 if (srv != SECSuccess) { 194 if (srv != SECSuccess) {
180 LOG(ERROR) << "PK11_ImportCert failed with error " << PORT_GetError(); 195 LOG(ERROR) << "PK11_ImportCert failed with error " << PORT_GetError();
181 not_imported->push_back(net::CertDatabase::ImportCertFailure( 196 not_imported->push_back(net::CertDatabase::ImportCertFailure(
182 cert, net::ERR_IMPORT_SERVER_CERT_FAILED)); 197 cert, net::ERR_IMPORT_SERVER_CERT_FAILED));
183 continue; 198 continue;
184 } 199 }
185 } 200 }
186 201
187 // Set as valid peer, but without any extra trust. 202 SetCertTrust(certificates[0].get(), net::SERVER_CERT, trustBits);
188 SetCertTrust(certificates[0].get(), net::SERVER_CERT,
189 net::CertDatabase::UNTRUSTED);
190 // TODO(mattm): Report SetCertTrust result? Putting in not_imported 203 // TODO(mattm): Report SetCertTrust result? Putting in not_imported
191 // wouldn't quite match up since it was imported... 204 // wouldn't quite match up since it was imported...
192 205
193 // Any errors importing individual certs will be in listed in |not_imported|. 206 // Any errors importing individual certs will be in listed in |not_imported|.
194 return true; 207 return true;
195 } 208 }
196 209
197 // Based on nsNSSCertificateDB::SetCertTrust. 210 // Based on nsNSSCertificateDB::SetCertTrust.
198 bool 211 bool
199 SetCertTrust(const net::X509Certificate* cert, 212 SetCertTrust(const net::X509Certificate* cert,
200 net::CertType type, 213 net::CertType type,
201 net::CertDatabase::TrustBits trustBits) 214 net::CertDatabase::TrustBits trustBits)
202 { 215 {
216 const unsigned kSSLTrustBits = net::CertDatabase::TRUSTED_SSL |
217 net::CertDatabase::DISTRUSTED_SSL;
218 const unsigned kEmailTrustBits = net::CertDatabase::TRUSTED_EMAIL |
219 net::CertDatabase::DISTRUSTED_EMAIL;
220 const unsigned kObjSignTrustBits = net::CertDatabase::TRUSTED_OBJ_SIGN |
221 net::CertDatabase::DISTRUSTED_OBJ_SIGN;
222 if ((trustBits & kSSLTrustBits) == kSSLTrustBits ||
223 (trustBits & kEmailTrustBits) == kEmailTrustBits ||
224 (trustBits & kObjSignTrustBits) == kObjSignTrustBits) {
225 LOG(ERROR) << "SetCertTrust called with conflicting trust bits "
226 << trustBits;
227 NOTREACHED();
228 return false;
229 }
230
203 SECStatus srv; 231 SECStatus srv;
204 nsNSSCertTrust trust;
205 CERTCertificate *nsscert = cert->os_cert_handle(); 232 CERTCertificate *nsscert = cert->os_cert_handle();
206 if (type == net::CA_CERT) { 233 if (type == net::CA_CERT) {
207 // always start with untrusted and move up 234 // Note that we start with CERTDB_VALID_CA for default trust and explicit
208 trust.SetValidCA(); 235 // trust, but explicitly distrusted usages will be set to
209 trust.AddCATrust(trustBits & net::CertDatabase::TRUSTED_SSL, 236 // CERTDB_TERMINAL_RECORD only.
210 trustBits & net::CertDatabase::TRUSTED_EMAIL, 237 CERTCertTrust trust = {CERTDB_VALID_CA, CERTDB_VALID_CA, CERTDB_VALID_CA};
211 trustBits & net::CertDatabase::TRUSTED_OBJ_SIGN); 238
212 srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), 239 if (trustBits & net::CertDatabase::DISTRUSTED_SSL)
213 nsscert, 240 trust.sslFlags = CERTDB_TERMINAL_RECORD;
214 trust.GetTrust()); 241 else if (trustBits & net::CertDatabase::TRUSTED_SSL)
242 trust.sslFlags |= CERTDB_TRUSTED_CA | CERTDB_TRUSTED_CLIENT_CA;
243
244 if (trustBits & net::CertDatabase::DISTRUSTED_EMAIL)
245 trust.emailFlags = CERTDB_TERMINAL_RECORD;
246 else if (trustBits & net::CertDatabase::TRUSTED_EMAIL)
247 trust.emailFlags |= CERTDB_TRUSTED_CA | CERTDB_TRUSTED_CLIENT_CA;
248
249 if (trustBits & net::CertDatabase::DISTRUSTED_OBJ_SIGN)
250 trust.objectSigningFlags = CERTDB_TERMINAL_RECORD;
251 else if (trustBits & net::CertDatabase::TRUSTED_OBJ_SIGN)
252 trust.objectSigningFlags |= CERTDB_TRUSTED_CA | CERTDB_TRUSTED_CLIENT_CA;
253
254 srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), nsscert, &trust);
215 } else if (type == net::SERVER_CERT) { 255 } else if (type == net::SERVER_CERT) {
216 // always start with untrusted and move up 256 CERTCertTrust trust = {0};
217 trust.SetValidPeer(); 257 // We only modify the sslFlags, so copy the other flags.
218 trust.AddPeerTrust(trustBits & net::CertDatabase::TRUSTED_SSL, 0, 0); 258 CERT_GetCertTrust(nsscert, &trust);
219 srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), 259 trust.sslFlags = 0;
220 nsscert, 260
221 trust.GetTrust()); 261 if (trustBits & net::CertDatabase::DISTRUSTED_SSL)
262 trust.sslFlags |= CERTDB_TERMINAL_RECORD;
263 else if (trustBits & net::CertDatabase::TRUSTED_SSL)
264 trust.sslFlags |= CERTDB_TRUSTED | CERTDB_TERMINAL_RECORD;
265
266 srv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), nsscert, &trust);
222 } else { 267 } else {
223 // ignore user and email/unknown certs 268 // ignore user and email/unknown certs
224 return true; 269 return true;
225 } 270 }
226 if (srv != SECSuccess) 271 if (srv != SECSuccess)
227 LOG(ERROR) << "SetCertTrust failed with error " << PORT_GetError(); 272 LOG(ERROR) << "SetCertTrust failed with error " << PORT_GetError();
228 return srv == SECSuccess; 273 return srv == SECSuccess;
229 } 274 }
230 275
231 } // namespace mozilla_security_manager 276 } // namespace mozilla_security_manager
OLDNEW
« no previous file with comments | « net/third_party/mozilla_security_manager/nsNSSCertificateDB.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698