Commit c0787704 authored by davidben@chromium.org's avatar davidben@chromium.org

Populate cert_key_types on OpenSSL.

Add a test to ensure it gets plumbed through correctly.

This also rolls third_party/openssl to r270417:
------------------------------------------------------------------------
r269864 | davidben@chromium.org | 2014-05-12 16:21:12 -0400 (Mon, 12 May 2014) | 7 lines

Add SSL_get_client_certificate_types.

Exposes the certificate_types parameter in a CertificateRequest.

BUG=165446

Review URL: https://codereview.chromium.org/254723002
------------------------------------------------------------------------
r270417 | davidben@chromium.org | 2014-05-14 12:27:52 -0400 (Wed, 14 May 2014) | 10 lines

Refactor ssl3_send_client_verify.

The original logic was a confusing spaghetti and mixed up initialization for
all the different cases together. Tidy it up in preparation for having to
adjust this logic later to support asynchronous crypto operations.

BUG=none
R=agl@chromium.org

Review URL: https://codereview.chromium.org//284693002
------------------------------------------------------------------------


BUG=165446

Review URL: https://codereview.chromium.org/257513008

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@271765 0039d316-1c4b-4281-b951-d872f2087c98
parent e36de125
......@@ -65,7 +65,7 @@ vars = {
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling openssl
# and whatever else without interference from each other.
"openssl_revision": "269063",
"openssl_revision": "270417",
# Three lines of non-changing comments so that
# the commit queue can handle CLs rolling ANGLE
# and whatever else without interference from each other.
......
......@@ -370,6 +370,7 @@ void SSLClientSocketOpenSSL::GetSSLCertRequestInfo(
SSLCertRequestInfo* cert_request_info) {
cert_request_info->host_and_port = host_and_port_;
cert_request_info->cert_authorities = cert_authorities_;
cert_request_info->cert_key_types = cert_key_types_;
}
SSLClientSocket::NextProtoStatus SSLClientSocketOpenSSL::GetNextProto(
......@@ -473,6 +474,7 @@ void SSLClientSocketOpenSSL::Disconnect() {
completed_handshake_ = false;
cert_authorities_.clear();
cert_key_types_.clear();
client_auth_cert_needed_ = false;
}
......@@ -1264,7 +1266,6 @@ int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl,
DCHECK(ssl == ssl_);
DCHECK(*x509 == NULL);
DCHECK(*pkey == NULL);
#if defined(USE_OPENSSL_CERTS)
if (!ssl_config_.send_client_cert) {
// First pass: we know that a client certificate is needed, but we do not
// have one at hand.
......@@ -1280,11 +1281,21 @@ int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl,
OPENSSL_free(str);
}
const unsigned char* client_cert_types;
size_t num_client_cert_types;
SSL_get_client_certificate_types(ssl, &client_cert_types,
&num_client_cert_types);
for (size_t i = 0; i < num_client_cert_types; i++) {
cert_key_types_.push_back(
static_cast<SSLClientCertType>(client_cert_types[i]));
}
return -1; // Suspends handshake.
}
// Second pass: a client certificate should have been selected.
if (ssl_config_.client_cert.get()) {
#if defined(USE_OPENSSL_CERTS)
// A note about ownership: FetchClientCertPrivateKey() increments
// the reference count of the EVP_PKEY. Ownership of this reference
// is passed directly to OpenSSL, which will release the reference
......@@ -1300,11 +1311,11 @@ int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl,
return 1;
}
LOG(WARNING) << "Client cert found without private key";
}
#else // !defined(USE_OPENSSL_CERTS)
// OS handling of client certificates is not yet implemented.
NOTIMPLEMENTED();
// OS handling of client certificates is not yet implemented.
NOTIMPLEMENTED();
#endif // defined(USE_OPENSSL_CERTS)
}
// Send no client certificate.
return 0;
......
......@@ -16,6 +16,7 @@
#include "net/socket/client_socket_handle.h"
#include "net/socket/ssl_client_socket.h"
#include "net/ssl/server_bound_cert_service.h"
#include "net/ssl/ssl_client_cert_type.h"
#include "net/ssl/ssl_config_service.h"
// Avoid including misc OpenSSL headers, i.e.:
......@@ -197,6 +198,9 @@ class SSLClientSocketOpenSSL : public SSLClientSocket {
// List of DER-encoded X.509 DistinguishedName of certificate authorities
// allowed by the server.
std::vector<std::string> cert_authorities_;
// List of SSLClientCertType values for client certificates allowed by the
// server.
std::vector<SSLClientCertType> cert_key_types_;
CertVerifier* const cert_verifier_;
scoped_ptr<SingleRequestCertVerifier> verifier_;
......
......@@ -704,6 +704,8 @@ class SSLClientSocketCertRequestInfoTest : public SSLClientSocketTest {
sock->GetSSLCertRequestInfo(request_info.get());
sock->Disconnect();
EXPECT_FALSE(sock->IsConnected());
EXPECT_TRUE(
test_server.host_port_pair().Equals(request_info->host_and_port));
return request_info;
}
......@@ -2219,6 +2221,21 @@ TEST_F(SSLClientSocketCertRequestInfoTest, TwoAuthorities) {
request_info->cert_authorities[1]);
}
// cert_key_types is currently only populated on OpenSSL.
#if defined(USE_OPENSSL)
TEST_F(SSLClientSocketCertRequestInfoTest, CertKeyTypes) {
SpawnedTestServer::SSLOptions ssl_options;
ssl_options.request_client_certificate = true;
ssl_options.client_cert_types.push_back(CLIENT_CERT_RSA_SIGN);
ssl_options.client_cert_types.push_back(CLIENT_CERT_ECDSA_SIGN);
scoped_refptr<SSLCertRequestInfo> request_info = GetCertRequest(ssl_options);
ASSERT_TRUE(request_info.get());
ASSERT_EQ(2u, request_info->cert_key_types.size());
EXPECT_EQ(CLIENT_CERT_RSA_SIGN, request_info->cert_key_types[0]);
EXPECT_EQ(CLIENT_CERT_ECDSA_SIGN, request_info->cert_key_types[1]);
}
#endif // defined(USE_OPENSSL)
TEST_F(SSLClientSocketTest, ConnectSignedCertTimestampsEnabledTLSExtension) {
SpawnedTestServer::SSLOptions ssl_options;
ssl_options.signed_cert_timestamps_tls_ext = "test";
......
......@@ -40,6 +40,20 @@ std::string GetHostname(BaseTestServer::Type type,
return BaseTestServer::kLocalhost;
}
std::string GetClientCertType(SSLClientCertType type) {
switch (type) {
case CLIENT_CERT_RSA_SIGN:
return "rsa_sign";
case CLIENT_CERT_DSS_SIGN:
return "dss_sign";
case CLIENT_CERT_ECDSA_SIGN:
return "ecdsa_sign";
default:
NOTREACHED();
return "";
}
}
void GetKeyExchangesList(int key_exchange, base::ListValue* values) {
if (key_exchange & BaseTestServer::SSLOptions::KEY_EXCHANGE_RSA)
values->Append(new base::StringValue("rsa"));
......@@ -386,6 +400,14 @@ bool BaseTestServer::GenerateArguments(base::DictionaryValue* arguments) const {
if (ssl_client_certs->GetSize())
arguments->Set("ssl-client-ca", ssl_client_certs.release());
scoped_ptr<base::ListValue> client_cert_types(new base::ListValue());
for (size_t i = 0; i < ssl_options_.client_cert_types.size(); i++) {
client_cert_types->Append(new base::StringValue(
GetClientCertType(ssl_options_.client_cert_types[i])));
}
if (client_cert_types->GetSize())
arguments->Set("ssl-client-cert-type", client_cert_types.release());
}
if (type_ == TYPE_HTTPS) {
......
......@@ -13,6 +13,7 @@
#include "base/files/file_path.h"
#include "base/memory/scoped_ptr.h"
#include "net/base/host_port_pair.h"
#include "net/ssl/ssl_client_cert_type.h"
class GURL;
......@@ -146,6 +147,11 @@ class BaseTestServer {
// field of the CertificateRequest.
std::vector<base::FilePath> client_authorities;
// If |request_client_certificate| is true, an optional list of
// SSLClientCertType values to populate the certificate_types field of the
// CertificateRequest.
std::vector<SSLClientCertType> client_cert_types;
// A bitwise-OR of KeyExchnage that should be used by the
// HTTPS server, or KEY_EXCHANGE_ANY to indicate that all implemented
// key exchange algorithms are acceptable.
......
......@@ -152,7 +152,7 @@ class HTTPSServer(tlslite.api.TLSSocketServerMixIn,
client verification."""
def __init__(self, server_address, request_hander_class, pem_cert_and_key,
ssl_client_auth, ssl_client_cas,
ssl_client_auth, ssl_client_cas, ssl_client_cert_types,
ssl_bulk_ciphers, ssl_key_exchanges, enable_npn,
record_resume_info, tls_intolerant, signed_cert_timestamps,
fallback_scsv_enabled, ocsp_response):
......@@ -167,6 +167,7 @@ class HTTPSServer(tlslite.api.TLSSocketServerMixIn,
implementations=['python'])
self.ssl_client_auth = ssl_client_auth
self.ssl_client_cas = []
self.ssl_client_cert_types = []
if enable_npn:
self.next_protos = ['http/1.1']
else:
......@@ -179,11 +180,20 @@ class HTTPSServer(tlslite.api.TLSSocketServerMixIn,
self.fallback_scsv_enabled = fallback_scsv_enabled
self.ocsp_response = ocsp_response
for ca_file in ssl_client_cas:
s = open(ca_file).read()
x509 = tlslite.api.X509()
x509.parse(s)
self.ssl_client_cas.append(x509.subject)
if ssl_client_auth:
for ca_file in ssl_client_cas:
s = open(ca_file).read()
x509 = tlslite.api.X509()
x509.parse(s)
self.ssl_client_cas.append(x509.subject)
for cert_type in ssl_client_cert_types:
self.ssl_client_cert_types.append({
"rsa_sign": tlslite.api.ClientCertificateType.rsa_sign,
"dss_sign": tlslite.api.ClientCertificateType.dss_sign,
"ecdsa_sign": tlslite.api.ClientCertificateType.ecdsa_sign,
}[cert_type])
self.ssl_handshake_settings = tlslite.api.HandshakeSettings()
if ssl_bulk_ciphers is not None:
self.ssl_handshake_settings.cipherNames = ssl_bulk_ciphers
......@@ -211,6 +221,7 @@ class HTTPSServer(tlslite.api.TLSSocketServerMixIn,
reqCert=self.ssl_client_auth,
settings=self.ssl_handshake_settings,
reqCAs=self.ssl_client_cas,
reqCertTypes=self.ssl_client_cert_types,
nextProtos=self.next_protos,
tlsIntolerant=self.tls_intolerant,
signedCertTimestamps=
......@@ -1989,6 +2000,7 @@ class ServerRunner(testserver_base.TestServerRunner):
server = HTTPSServer((host, port), TestPageHandler, pem_cert_and_key,
self.options.ssl_client_auth,
self.options.ssl_client_ca,
self.options.ssl_client_cert_type,
self.options.ssl_bulk_cipher,
self.options.ssl_key_exchange,
self.options.enable_npn,
......@@ -2172,6 +2184,15 @@ class ServerRunner(testserver_base.TestServerRunner):
'file. This option may appear multiple '
'times, indicating multiple CA names should '
'be sent in the request.')
self.option_parser.add_option('--ssl-client-cert-type', action='append',
default=[], help='Specify that the client '
'certificate request should include the '
'specified certificate_type value. This '
'option may appear multiple times, '
'indicating multiple values should be send '
'in the request. Valid values are '
'"rsa_sign", "dss_sign", and "ecdsa_sign". '
'If omitted, "rsa_sign" will be used.')
self.option_parser.add_option('--ssl-bulk-cipher', action='append',
help='Specify the bulk encryption '
'algorithm(s) that will be accepted by the '
......
......@@ -31,3 +31,5 @@ Local Modifications:
- patches/fix_test_file.patch: Fix #! line in random test file to appease our
presubmit checks.
- patches/dhe_rsa.patch: Implement DHE_RSA-based cipher suites.
- patches/req_cert_types.patch: Add a reqCertTypes parameter to populate the
certificate_types field of CertificateRequest.
diff --git a/third_party/tlslite/tlslite/api.py b/third_party/tlslite/tlslite/api.py
index faef6cb..562fb81 100644
--- a/third_party/tlslite/tlslite/api.py
+++ b/third_party/tlslite/tlslite/api.py
@@ -2,7 +2,8 @@
# See the LICENSE file for legal information regarding use of this file.
__version__ = "0.4.6"
-from .constants import AlertLevel, AlertDescription, Fault
+from .constants import AlertLevel, AlertDescription, ClientCertificateType, \
+ Fault
from .errors import *
from .checker import Checker
from .handshakesettings import HandshakeSettings
diff --git a/third_party/tlslite/tlslite/constants.py b/third_party/tlslite/tlslite/constants.py
index 30d1f9f..457b339 100644
--- a/third_party/tlslite/tlslite/constants.py
+++ b/third_party/tlslite/tlslite/constants.py
@@ -14,10 +14,14 @@ class CertificateType:
openpgp = 1
class ClientCertificateType:
+ # http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-2
rsa_sign = 1
dss_sign = 2
rsa_fixed_dh = 3
dss_fixed_dh = 4
+ ecdsa_sign = 64
+ rsa_fixed_ecdh = 65
+ ecdsa_fixed_ecdh = 66
class HandshakeType:
hello_request = 0
diff --git a/third_party/tlslite/tlslite/messages.py b/third_party/tlslite/tlslite/messages.py
index 550b387..c8a913c 100644
--- a/third_party/tlslite/tlslite/messages.py
+++ b/third_party/tlslite/tlslite/messages.py
@@ -454,9 +454,7 @@ class CertificateStatus(HandshakeMsg):
class CertificateRequest(HandshakeMsg):
def __init__(self):
HandshakeMsg.__init__(self, HandshakeType.certificate_request)
- #Apple's Secure Transport library rejects empty certificate_types, so
- #default to rsa_sign.
- self.certificate_types = [ClientCertificateType.rsa_sign]
+ self.certificate_types = []
self.certificate_authorities = []
def create(self, certificate_types, certificate_authorities):
diff --git a/third_party/tlslite/tlslite/tlsconnection.py b/third_party/tlslite/tlslite/tlsconnection.py
index e6f7820..044ad59 100644
--- a/third_party/tlslite/tlslite/tlsconnection.py
+++ b/third_party/tlslite/tlslite/tlsconnection.py
@@ -1062,7 +1062,7 @@ class TLSConnection(TLSRecordLayer):
def handshakeServer(self, verifierDB=None,
certChain=None, privateKey=None, reqCert=False,
sessionCache=None, settings=None, checker=None,
- reqCAs = None,
+ reqCAs = None, reqCertTypes = None,
tacks=None, activationFlags=0,
nextProtos=None, anon=False,
tlsIntolerant=None, signedCertTimestamps=None,
@@ -1130,6 +1130,10 @@ class TLSConnection(TLSRecordLayer):
will be sent along with a certificate request. This does not affect
verification.
+ @type reqCertTypes: list of int
+ @param reqCertTypes: A list of certificate_type values to be sent
+ along with a certificate request. This does not affect verification.
+
@type nextProtos: list of strings.
@param nextProtos: A list of upper layer protocols to expose to the
clients through the Next-Protocol Negotiation Extension,
@@ -1169,7 +1173,7 @@ class TLSConnection(TLSRecordLayer):
"""
for result in self.handshakeServerAsync(verifierDB,
certChain, privateKey, reqCert, sessionCache, settings,
- checker, reqCAs,
+ checker, reqCAs, reqCertTypes,
tacks=tacks, activationFlags=activationFlags,
nextProtos=nextProtos, anon=anon, tlsIntolerant=tlsIntolerant,
signedCertTimestamps=signedCertTimestamps,
@@ -1180,7 +1184,7 @@ class TLSConnection(TLSRecordLayer):
def handshakeServerAsync(self, verifierDB=None,
certChain=None, privateKey=None, reqCert=False,
sessionCache=None, settings=None, checker=None,
- reqCAs=None,
+ reqCAs=None, reqCertTypes=None,
tacks=None, activationFlags=0,
nextProtos=None, anon=False,
tlsIntolerant=None,
@@ -1203,7 +1207,7 @@ class TLSConnection(TLSRecordLayer):
verifierDB=verifierDB, certChain=certChain,
privateKey=privateKey, reqCert=reqCert,
sessionCache=sessionCache, settings=settings,
- reqCAs=reqCAs,
+ reqCAs=reqCAs, reqCertTypes=reqCertTypes,
tacks=tacks, activationFlags=activationFlags,
nextProtos=nextProtos, anon=anon,
tlsIntolerant=tlsIntolerant,
@@ -1216,7 +1220,7 @@ class TLSConnection(TLSRecordLayer):
def _handshakeServerAsyncHelper(self, verifierDB,
certChain, privateKey, reqCert, sessionCache,
- settings, reqCAs,
+ settings, reqCAs, reqCertTypes,
tacks, activationFlags,
nextProtos, anon,
tlsIntolerant, signedCertTimestamps, fallbackSCSV,
@@ -1232,6 +1236,8 @@ class TLSConnection(TLSRecordLayer):
raise ValueError("Caller passed a privateKey but no certChain")
if reqCAs and not reqCert:
raise ValueError("Caller passed reqCAs but not reqCert")
+ if reqCertTypes and not reqCert:
+ raise ValueError("Caller passed reqCertTypes but not reqCert")
if certChain and not isinstance(certChain, X509CertChain):
raise ValueError("Unrecognized certificate type")
if activationFlags and not tacks:
@@ -1320,7 +1326,7 @@ class TLSConnection(TLSRecordLayer):
assert(False)
for result in self._serverCertKeyExchange(clientHello, serverHello,
certChain, keyExchange,
- reqCert, reqCAs, cipherSuite,
+ reqCert, reqCAs, reqCertTypes, cipherSuite,
settings, ocspResponse):
if result in (0,1): yield result
else: break
@@ -1597,7 +1603,7 @@ class TLSConnection(TLSRecordLayer):
def _serverCertKeyExchange(self, clientHello, serverHello,
serverCertChain, keyExchange,
- reqCert, reqCAs, cipherSuite,
+ reqCert, reqCAs, reqCertTypes, cipherSuite,
settings, ocspResponse):
#Send ServerHello, Certificate[, ServerKeyExchange]
#[, CertificateRequest], ServerHelloDone
@@ -1613,11 +1619,12 @@ class TLSConnection(TLSRecordLayer):
serverKeyExchange = keyExchange.makeServerKeyExchange()
if serverKeyExchange is not None:
msgs.append(serverKeyExchange)
- if reqCert and reqCAs:
- msgs.append(CertificateRequest().create(\
- [ClientCertificateType.rsa_sign], reqCAs))
- elif reqCert:
- msgs.append(CertificateRequest())
+ if reqCert:
+ reqCAs = reqCAs or []
+ #Apple's Secure Transport library rejects empty certificate_types,
+ #so default to rsa_sign.
+ reqCertTypes = reqCertTypes or [ClientCertificateType.rsa_sign]
+ msgs.append(CertificateRequest().create(reqCertTypes, reqCAs))
msgs.append(ServerHelloDone())
for result in self._sendMsgs(msgs):
yield result
......@@ -2,7 +2,8 @@
# See the LICENSE file for legal information regarding use of this file.
__version__ = "0.4.6"
from .constants import AlertLevel, AlertDescription, Fault
from .constants import AlertLevel, AlertDescription, ClientCertificateType, \
Fault
from .errors import *
from .checker import Checker
from .handshakesettings import HandshakeSettings
......
......@@ -14,10 +14,14 @@ class CertificateType:
openpgp = 1
class ClientCertificateType:
# http://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-2
rsa_sign = 1
dss_sign = 2
rsa_fixed_dh = 3
dss_fixed_dh = 4
ecdsa_sign = 64
rsa_fixed_ecdh = 65
ecdsa_fixed_ecdh = 66
class HandshakeType:
hello_request = 0
......
......@@ -454,9 +454,7 @@ class CertificateStatus(HandshakeMsg):
class CertificateRequest(HandshakeMsg):
def __init__(self):
HandshakeMsg.__init__(self, HandshakeType.certificate_request)
#Apple's Secure Transport library rejects empty certificate_types, so
#default to rsa_sign.
self.certificate_types = [ClientCertificateType.rsa_sign]
self.certificate_types = []
self.certificate_authorities = []
def create(self, certificate_types, certificate_authorities):
......
......@@ -1062,7 +1062,7 @@ class TLSConnection(TLSRecordLayer):
def handshakeServer(self, verifierDB=None,
certChain=None, privateKey=None, reqCert=False,
sessionCache=None, settings=None, checker=None,
reqCAs = None,
reqCAs = None, reqCertTypes = None,
tacks=None, activationFlags=0,
nextProtos=None, anon=False,
tlsIntolerant=None, signedCertTimestamps=None,
......@@ -1130,6 +1130,10 @@ class TLSConnection(TLSRecordLayer):
will be sent along with a certificate request. This does not affect
verification.
@type reqCertTypes: list of int
@param reqCertTypes: A list of certificate_type values to be sent
along with a certificate request. This does not affect verification.
@type nextProtos: list of strings.
@param nextProtos: A list of upper layer protocols to expose to the
clients through the Next-Protocol Negotiation Extension,
......@@ -1169,7 +1173,7 @@ class TLSConnection(TLSRecordLayer):
"""
for result in self.handshakeServerAsync(verifierDB,
certChain, privateKey, reqCert, sessionCache, settings,
checker, reqCAs,
checker, reqCAs, reqCertTypes,
tacks=tacks, activationFlags=activationFlags,
nextProtos=nextProtos, anon=anon, tlsIntolerant=tlsIntolerant,
signedCertTimestamps=signedCertTimestamps,
......@@ -1180,7 +1184,7 @@ class TLSConnection(TLSRecordLayer):
def handshakeServerAsync(self, verifierDB=None,
certChain=None, privateKey=None, reqCert=False,
sessionCache=None, settings=None, checker=None,
reqCAs=None,
reqCAs=None, reqCertTypes=None,
tacks=None, activationFlags=0,
nextProtos=None, anon=False,
tlsIntolerant=None,
......@@ -1203,7 +1207,7 @@ class TLSConnection(TLSRecordLayer):
verifierDB=verifierDB, certChain=certChain,
privateKey=privateKey, reqCert=reqCert,
sessionCache=sessionCache, settings=settings,
reqCAs=reqCAs,
reqCAs=reqCAs, reqCertTypes=reqCertTypes,
tacks=tacks, activationFlags=activationFlags,
nextProtos=nextProtos, anon=anon,
tlsIntolerant=tlsIntolerant,
......@@ -1216,7 +1220,7 @@ class TLSConnection(TLSRecordLayer):
def _handshakeServerAsyncHelper(self, verifierDB,
certChain, privateKey, reqCert, sessionCache,
settings, reqCAs,
settings, reqCAs, reqCertTypes,
tacks, activationFlags,
nextProtos, anon,
tlsIntolerant, signedCertTimestamps, fallbackSCSV,
......@@ -1232,6 +1236,8 @@ class TLSConnection(TLSRecordLayer):
raise ValueError("Caller passed a privateKey but no certChain")
if reqCAs and not reqCert:
raise ValueError("Caller passed reqCAs but not reqCert")
if reqCertTypes and not reqCert:
raise ValueError("Caller passed reqCertTypes but not reqCert")
if certChain and not isinstance(certChain, X509CertChain):
raise ValueError("Unrecognized certificate type")
if activationFlags and not tacks:
......@@ -1320,7 +1326,7 @@ class TLSConnection(TLSRecordLayer):
assert(False)
for result in self._serverCertKeyExchange(clientHello, serverHello,
certChain, keyExchange,
reqCert, reqCAs, cipherSuite,
reqCert, reqCAs, reqCertTypes, cipherSuite,
settings, ocspResponse):
if result in (0,1): yield result
else: break
......@@ -1597,7 +1603,7 @@ class TLSConnection(TLSRecordLayer):
def _serverCertKeyExchange(self, clientHello, serverHello,
serverCertChain, keyExchange,
reqCert, reqCAs, cipherSuite,
reqCert, reqCAs, reqCertTypes, cipherSuite,
settings, ocspResponse):
#Send ServerHello, Certificate[, ServerKeyExchange]
#[, CertificateRequest], ServerHelloDone
......@@ -1613,11 +1619,12 @@ class TLSConnection(TLSRecordLayer):
serverKeyExchange = keyExchange.makeServerKeyExchange()
if serverKeyExchange is not None:
msgs.append(serverKeyExchange)
if reqCert and reqCAs:
msgs.append(CertificateRequest().create(\
[ClientCertificateType.rsa_sign], reqCAs))
elif reqCert:
msgs.append(CertificateRequest())
if reqCert:
reqCAs = reqCAs or []
#Apple's Secure Transport library rejects empty certificate_types,
#so default to rsa_sign.
reqCertTypes = reqCertTypes or [ClientCertificateType.rsa_sign]
msgs.append(CertificateRequest().create(reqCertTypes, reqCAs))
msgs.append(ServerHelloDone())
for result in self._sendMsgs(msgs):
yield result
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment