mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
bug 1009161 - mozilla::pkix: allow the Netscape certificate type extension if more standardized information is present r=briansmith
This commit is contained in:
parent
c6070203fb
commit
0eb37ae230
27
security/manager/ssl/tests/unit/test_nsCertType.js
Normal file
27
security/manager/ssl/tests/unit/test_nsCertType.js
Normal file
@ -0,0 +1,27 @@
|
||||
// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
|
||||
// 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/.
|
||||
//
|
||||
// While the Netscape certificate type extension is not a standard and has been
|
||||
// discouraged from use for quite some time, it is still encountered. Thus, we
|
||||
// handle it slightly differently from other unknown extensions.
|
||||
// If it is not marked critical, we ignore it.
|
||||
// If it is marked critical:
|
||||
// If the basic constraints and extended key usage extensions are also
|
||||
// present, we ignore it, because they are standardized and should convey the
|
||||
// same information.
|
||||
// Otherwise, we reject it with an error indicating an unknown critical
|
||||
// extension.
|
||||
|
||||
"use strict";
|
||||
|
||||
function run_test() {
|
||||
do_get_profile();
|
||||
add_tls_server_setup("BadCertServer");
|
||||
add_connection_test("nsCertTypeNotCritical.example.com", Cr.NS_OK);
|
||||
add_connection_test("nsCertTypeCriticalWithExtKeyUsage.example.com", Cr.NS_OK);
|
||||
add_connection_test("nsCertTypeCritical.example.com",
|
||||
getXPCOMStatusFromNSS(SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION));
|
||||
run_next_test();
|
||||
}
|
Binary file not shown.
@ -53,6 +53,9 @@ const BadCertHost sBadCertHosts[] =
|
||||
{ "exclude-subdomains.pinning.example.com", "localhostAndExampleCom" },
|
||||
{ "sub.exclude-subdomains.pinning.example.com", "otherIssuerEE" },
|
||||
{ "test-mode.pinning.example.com", "otherIssuerEE" },
|
||||
{ "nsCertTypeNotCritical.example.com", "nsCertTypeNotCritical" },
|
||||
{ "nsCertTypeCriticalWithExtKeyUsage.example.com", "nsCertTypeCriticalWithExtKeyUsage" },
|
||||
{ "nsCertTypeCritical.example.com", "nsCertTypeCritical" },
|
||||
{ nullptr, nullptr }
|
||||
};
|
||||
|
||||
|
@ -172,6 +172,37 @@ function make_EE {
|
||||
SERIALNO=$(($SERIALNO + 1))
|
||||
}
|
||||
|
||||
function make_EE_with_nsCertType {
|
||||
NICKNAME="${1}"
|
||||
SUBJECT="${2}"
|
||||
CA="${3}"
|
||||
SUBJECT_ALT_NAME="${4}"
|
||||
NS_CERT_TYPE_CRITICAL="${5}"
|
||||
EXTRA_ARGS="${6}"
|
||||
# This adds the Netscape certificate type extension with the "sslServer"
|
||||
# bit asserted. Its criticality depends on if "y" or "n" was passed as
|
||||
# an argument to this function.
|
||||
CERT_RESPONSES="n\n\ny\n1\n8\n$NS_CERT_TYPE_CRITICAL\n"
|
||||
|
||||
cert_already_exists $NICKNAME
|
||||
if [ $ALREADY_EXISTS -eq 1 ]; then
|
||||
echo "cert \"$NICKNAME\" already exists - not regenerating it (use --clobber to force regeneration)"
|
||||
return
|
||||
fi
|
||||
|
||||
echo -e "$CERT_RESPONSES" | $RUN_MOZILLA $CERTUTIL -d $DB_ARGUMENT -S \
|
||||
-n $NICKNAME \
|
||||
-s "$SUBJECT" \
|
||||
-8 $SUBJECT_ALT_NAME \
|
||||
-c $CA \
|
||||
-t ",," \
|
||||
-m $SERIALNO \
|
||||
-5 \
|
||||
$COMMON_ARGS \
|
||||
$EXTRA_ARGS
|
||||
SERIALNO=$(($SERIALNO + 1))
|
||||
}
|
||||
|
||||
function make_delegated {
|
||||
CERT_RESPONSES="n\n\ny\n"
|
||||
NICKNAME="${1}"
|
||||
@ -251,4 +282,8 @@ make_INT self-signed-EE-with-cA-true 'CN=Test Self-signed End-entity with CA tru
|
||||
|
||||
make_delegated badKeysizeDelegatedSigner 'CN=Bad Keysize Delegated Responder' testCA "--extKeyUsage ocspResponder -g 1008"
|
||||
|
||||
make_EE_with_nsCertType nsCertTypeCritical 'CN=nsCertType Critical' testCA "localhost,*.example.com" "y"
|
||||
make_EE_with_nsCertType nsCertTypeNotCritical 'CN=nsCertType Not Critical' testCA "localhost,*.example.com" "n"
|
||||
make_EE_with_nsCertType nsCertTypeCriticalWithExtKeyUsage 'CN=nsCertType Critical With extKeyUsage' testCA "localhost,*.example.com" "y" "--extKeyUsage serverAuth"
|
||||
|
||||
cleanup
|
||||
|
Binary file not shown.
@ -62,6 +62,7 @@ using std::placeholders::_3;
|
||||
extern class Placeholder1 { } _1;
|
||||
extern class Placeholder2 { } _2;
|
||||
extern class Placeholder3 { } _3;
|
||||
extern class Placeholder4 { } _4;
|
||||
|
||||
template <typename V> V& ref(V& v) { return v; }
|
||||
template <typename V> const V& cref(const V& v) { return v; }
|
||||
@ -113,17 +114,18 @@ private:
|
||||
void operator=(const Bind4&) /*= delete*/;
|
||||
};
|
||||
|
||||
template <typename R, typename C1, typename P1, typename P2, typename P3>
|
||||
class BindToMemberFunction3
|
||||
template <typename R, typename C1, typename P1, typename P2, typename P3,
|
||||
typename P4>
|
||||
class BindToMemberFunction4
|
||||
{
|
||||
public:
|
||||
typedef R (C1::*F)(P1&, P2&, P3&);
|
||||
BindToMemberFunction3(F f, C1* that) : f(f), that(that) { }
|
||||
R operator()(P1& p1, P2& p2, P3& p3) const { return (that->*f)(p1, p2, p3); }
|
||||
typedef R (C1::*F)(P1&, P2&, P3, P4&);
|
||||
BindToMemberFunction4(F f, C1* that) : f(f), that(that) { }
|
||||
R operator()(P1& p1, P2& p2, P3 p3, P4& p4) const { return (that->*f)(p1, p2, p3, p4); }
|
||||
private:
|
||||
const F f;
|
||||
C1* const that;
|
||||
void operator=(const BindToMemberFunction3&) /*= delete*/;
|
||||
void operator=(const BindToMemberFunction4&) /*= delete*/;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
@ -151,12 +153,13 @@ bind(R (*f)(P1&, B1, B2, B3&, B4&), Placeholder1&, const B1& b1, const B2& b2,
|
||||
return internal::Bind4<R, P1, const B1, const B2, B3, B4>(f, b1, b2, b3, b4);
|
||||
}
|
||||
|
||||
template <typename R, typename C1, typename P1, typename P2, typename P3>
|
||||
inline internal::BindToMemberFunction3<R, C1, P1, P2, P3>
|
||||
bind(R (C1::*f)(P1&, P2&, P3&), C1* that, Placeholder1&, Placeholder2&,
|
||||
Placeholder3&)
|
||||
template <typename R, typename C1, typename P1, typename P2, typename P3,
|
||||
typename P4>
|
||||
inline internal::BindToMemberFunction4<R, C1, P1, P2, P3, P4>
|
||||
bind(R (C1::*f)(P1&, P2&, P3, P4&), C1* that, Placeholder1&, Placeholder2&,
|
||||
Placeholder3, Placeholder4&)
|
||||
{
|
||||
return internal::BindToMemberFunction3<R, C1, P1, P2, P3>(f, that);
|
||||
return internal::BindToMemberFunction4<R, C1, P1, P2, P3, P4>(f, that);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -31,6 +31,7 @@ namespace mozilla { namespace pkix {
|
||||
Placeholder1 _1;
|
||||
Placeholder2 _2;
|
||||
Placeholder3 _3;
|
||||
Placeholder4 _4;
|
||||
|
||||
} } // namespace mozilla::pkix
|
||||
|
||||
|
@ -152,10 +152,37 @@ BackCert::Init()
|
||||
if (version == der::Version::v3 || version == der::Version::v4) {
|
||||
rv = der::OptionalExtensions(tbsCertificate, CSC | 3,
|
||||
bind(&BackCert::RememberExtension, this, _1,
|
||||
_2, _3));
|
||||
_2, _3, _4));
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
// The Netscape Certificate Type extension is an obsolete
|
||||
// Netscape-proprietary mechanism that we ignore in favor of the standard
|
||||
// extensions. However, some CAs have issued certificates with the Netscape
|
||||
// Cert Type extension marked critical. Thus, for compatibility reasons, we
|
||||
// "understand" this extension by ignoring it when it is not critical, and
|
||||
// by ensuring that the equivalent standardized extensions are present when
|
||||
// it is marked critical, based on the assumption that the information in
|
||||
// the Netscape Cert Type extension is consistent with the information in
|
||||
// the standard extensions.
|
||||
//
|
||||
// Here is a mapping between the Netscape Cert Type extension and the
|
||||
// standard extensions:
|
||||
//
|
||||
// Netscape Cert Type | BasicConstraints.cA | Extended Key Usage
|
||||
// --------------------+-----------------------+----------------------
|
||||
// SSL Server | false | id_kp_serverAuth
|
||||
// SSL Client | false | id_kp_clientAuth
|
||||
// S/MIME Client | false | id_kp_emailProtection
|
||||
// Object Signing | false | id_kp_codeSigning
|
||||
// SSL Server CA | true | id_pk_serverAuth
|
||||
// SSL Client CA | true | id_kp_clientAuth
|
||||
// S/MIME CA | true | id_kp_emailProtection
|
||||
// Object Signing CA | true | id_kp_codeSigning
|
||||
if (criticalNetscapeCertificateType.GetLength() > 0 &&
|
||||
(basicConstraints.GetLength() == 0 || extKeyUsage.GetLength() == 0)) {
|
||||
return Result::ERROR_UNKNOWN_CRITICAL_EXTENSION;
|
||||
}
|
||||
}
|
||||
|
||||
return der::End(tbsCertificate);
|
||||
@ -165,7 +192,7 @@ BackCert::Init()
|
||||
// to limitations in our std::bind polyfill.
|
||||
Result
|
||||
BackCert::RememberExtension(Reader& extnID, const Input& extnValue,
|
||||
/*out*/ bool& understood)
|
||||
bool critical, /*out*/ bool& understood)
|
||||
{
|
||||
understood = false;
|
||||
|
||||
@ -205,6 +232,10 @@ BackCert::RememberExtension(Reader& extnID, const Input& extnValue,
|
||||
static const uint8_t id_pe_authorityInfoAccess[] = {
|
||||
0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01
|
||||
};
|
||||
// python DottedOIDToCode.py Netscape-certificate-type 2.16.840.1.113730.1.1
|
||||
static const uint8_t Netscape_certificate_type[] = {
|
||||
0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x01
|
||||
};
|
||||
|
||||
Input* out = nullptr;
|
||||
|
||||
@ -238,6 +269,8 @@ BackCert::RememberExtension(Reader& extnID, const Input& extnValue,
|
||||
out = &inhibitAnyPolicy;
|
||||
} else if (extnID.MatchRest(id_pe_authorityInfoAccess)) {
|
||||
out = &authorityInfoAccess;
|
||||
} else if (extnID.MatchRest(Netscape_certificate_type) && critical) {
|
||||
out = &criticalNetscapeCertificateType;
|
||||
}
|
||||
|
||||
if (out) {
|
||||
|
@ -570,7 +570,7 @@ OptionalExtensions(Reader& input, uint8_t tag,
|
||||
}
|
||||
|
||||
bool understood = false;
|
||||
rv = extensionHandler(extnID, extnValue, understood);
|
||||
rv = extensionHandler(extnID, extnValue, critical, understood);
|
||||
if (rv != Success) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ static inline Result ResponseData(
|
||||
const DERArray& certs);
|
||||
static inline Result SingleResponse(Reader& input, Context& context);
|
||||
static Result ExtensionNotUnderstood(Reader& extnID, Input extnValue,
|
||||
/*out*/ bool& understood);
|
||||
bool critical, /*out*/ bool& understood);
|
||||
static inline Result CertID(Reader& input,
|
||||
const Context& context,
|
||||
/*out*/ bool& match);
|
||||
@ -824,7 +824,7 @@ KeyHash(TrustDomain& trustDomain, const Input subjectPublicKeyInfo,
|
||||
|
||||
Result
|
||||
ExtensionNotUnderstood(Reader& /*extnID*/, Input /*extnValue*/,
|
||||
/*out*/ bool& understood)
|
||||
bool /*critical*/, /*out*/ bool& understood)
|
||||
{
|
||||
understood = false;
|
||||
return Success;
|
||||
|
@ -134,9 +134,10 @@ private:
|
||||
Input keyUsage;
|
||||
Input nameConstraints;
|
||||
Input subjectAltName;
|
||||
Input criticalNetscapeCertificateType;
|
||||
|
||||
Result RememberExtension(Reader& extnID, const Input& extnValue,
|
||||
/*out*/ bool& understood);
|
||||
bool critical, /*out*/ bool& understood);
|
||||
|
||||
BackCert(const BackCert&) /* = delete */;
|
||||
void operator=(const BackCert&); /* = delete */;
|
||||
|
Loading…
Reference in New Issue
Block a user