mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-12-01 09:46:09 +03:00
108 lines
3.1 KiB
C++
108 lines
3.1 KiB
C++
|
/*
|
||
|
* NSS utility functions
|
||
|
*
|
||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||
|
|
||
|
#include "net/third_party/nss/ssl/cmpcert.h"
|
||
|
|
||
|
#include <secder.h>
|
||
|
#include <secitem.h>
|
||
|
|
||
|
#include "base/strings/string_piece.h"
|
||
|
#include "net/cert/internal/parse_certificate.h"
|
||
|
#include "net/cert/x509_certificate.h"
|
||
|
#include "net/cert/x509_util.h"
|
||
|
#include "net/der/parser.h"
|
||
|
#include "third_party/boringssl/src/include/openssl/pool.h"
|
||
|
|
||
|
namespace net {
|
||
|
|
||
|
namespace {
|
||
|
|
||
|
bool GetIssuerAndSubject(CERTCertificate* cert,
|
||
|
der::Input* issuer,
|
||
|
der::Input* subject) {
|
||
|
*issuer = der::Input(cert->derIssuer.data, cert->derIssuer.len);
|
||
|
*subject = der::Input(cert->derSubject.data, cert->derSubject.len);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
bool GetIssuerAndSubject(X509Certificate* cert,
|
||
|
der::Input* issuer,
|
||
|
der::Input* subject) {
|
||
|
der::Input tbs_certificate_tlv;
|
||
|
der::Input signature_algorithm_tlv;
|
||
|
der::BitString signature_value;
|
||
|
if (!ParseCertificate(der::Input(CRYPTO_BUFFER_data(cert->cert_buffer()),
|
||
|
CRYPTO_BUFFER_len(cert->cert_buffer())),
|
||
|
&tbs_certificate_tlv, &signature_algorithm_tlv,
|
||
|
&signature_value, nullptr)) {
|
||
|
return false;
|
||
|
}
|
||
|
ParsedTbsCertificate tbs;
|
||
|
if (!ParseTbsCertificate(tbs_certificate_tlv,
|
||
|
x509_util::DefaultParseCertificateOptions(), &tbs,
|
||
|
nullptr)) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
*issuer = tbs.issuer_tlv;
|
||
|
*subject = tbs.subject_tlv;
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
} // namespace
|
||
|
|
||
|
bool MatchClientCertificateIssuers(
|
||
|
X509Certificate* cert,
|
||
|
const std::vector<std::string>& cert_authorities,
|
||
|
ScopedCERTCertificateList* intermediates) {
|
||
|
// Bound how many iterations to try.
|
||
|
static const int kMaxDepth = 20;
|
||
|
|
||
|
intermediates->clear();
|
||
|
|
||
|
// If no authorities are supplied, everything matches.
|
||
|
if (cert_authorities.empty())
|
||
|
return true;
|
||
|
|
||
|
// DER encoded issuer and subject name of current certificate.
|
||
|
der::Input issuer;
|
||
|
der::Input subject;
|
||
|
|
||
|
if (!GetIssuerAndSubject(cert, &issuer, &subject))
|
||
|
return false;
|
||
|
|
||
|
while (intermediates->size() < kMaxDepth) {
|
||
|
// Check if current cert is issued by a valid CA.
|
||
|
for (const std::string& ca : cert_authorities) {
|
||
|
if (issuer == der::Input(&ca))
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
// Stop at self-issued certificates.
|
||
|
if (issuer == subject)
|
||
|
return false;
|
||
|
|
||
|
// Look the parent up in the database and keep searching.
|
||
|
SECItem issuer_item;
|
||
|
issuer_item.len = issuer.Length();
|
||
|
issuer_item.data = const_cast<unsigned char*>(issuer.UnsafeData());
|
||
|
ScopedCERTCertificate nextcert(
|
||
|
CERT_FindCertByName(CERT_GetDefaultCertDB(), &issuer_item));
|
||
|
if (!nextcert)
|
||
|
return false;
|
||
|
|
||
|
if (!GetIssuerAndSubject(nextcert.get(), &issuer, &subject))
|
||
|
return false;
|
||
|
|
||
|
intermediates->push_back(std::move(nextcert));
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
} // namespace net
|