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

Unified Diff: net/socket/ssl_client_socket_nss.cc

Issue 6804032: Add TLS-SRP (RFC 5054) support Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: remove "httpsv" scheme, minor NSS/OpenSSL changes Created 9 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/socket/ssl_client_socket_nss.h ('k') | net/socket/ssl_client_socket_tls_srp_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/socket/ssl_client_socket_nss.cc
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
index 384fa9d3bf2e6ae14d608e61ec71d680e01ea027..f4718aff4b02c1262f58120c354986ea374c5844 100644
--- a/net/socket/ssl_client_socket_nss.cc
+++ b/net/socket/ssl_client_socket_nss.cc
@@ -75,6 +75,7 @@
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "base/threading/thread_restrictions.h"
+#include "base/utf_string_conversions.h"
#include "base/values.h"
#include "net/base/address_list.h"
#include "net/base/cert_status_flags.h"
@@ -469,6 +470,7 @@ SSLClientSocketNSS::SSLClientSocketNSS(ClientSocketHandle* transport_socket,
completed_handshake_(false),
pseudo_connected_(false),
eset_mitm_detected_(false),
+ server_cert_needed_(true),
predicted_cert_chain_correct_(false),
peername_initialized_(false),
dnssec_provider_(NULL),
@@ -498,15 +500,21 @@ void SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
EnterFunction("");
ssl_info->Reset();
- if (!server_cert_) {
- LOG(DFATAL) << "!server_cert_";
+ if (!server_cert_ && server_cert_needed_) {
+ LOG(DFATAL) << "!server_cert_ && server_cert_needed_";
return;
}
- ssl_info->cert_status = server_cert_verify_result_->cert_status;
- DCHECK(server_cert_ != NULL);
- ssl_info->cert = server_cert_;
ssl_info->connection_status = ssl_connection_status_;
+ if (server_cert_verify_result_) {
+ ssl_info->cert_status = server_cert_verify_result_->cert_status;
+ }
+ if (server_cert_ != NULL) {
+ ssl_info->cert = server_cert_;
+ }
+ if (ssl_config_.use_tls_auth && !authenticated_tls_username_.empty()) {
+ ssl_info->tls_username = UTF8ToUTF16(authenticated_tls_username_);
+ }
PRUint16 cipher_suite =
SSLConnectionStatusToCipherSuite(ssl_connection_status_);
@@ -911,14 +919,6 @@ int SSLClientSocketNSS::InitializeSSLOptions() {
return ERR_UNEXPECTED;
}
- for (std::vector<uint16>::const_iterator it =
- ssl_config_.disabled_cipher_suites.begin();
- it != ssl_config_.disabled_cipher_suites.end(); ++it) {
- // This will fail if the specified cipher is not implemented by NSS, but
- // the failure is harmless.
- SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE);
- }
-
#ifdef SSL_ENABLE_SESSION_TICKETS
// Support RFC 5077
rv = SSL_OptionSet(nss_fd_, SSL_ENABLE_SESSION_TICKETS, PR_TRUE);
@@ -1029,6 +1029,43 @@ int SSLClientSocketNSS::InitializeSSLOptions() {
return ERR_UNEXPECTED;
}
+ if (ssl_config_.use_tls_auth) {
+ // Enable SRP ciphers, and disable non-SRP ciphers if we *require* TLS auth.
+ rv = SetCiphersForTLSAuth(true, ssl_config_.require_tls_auth);
+ if (rv != OK)
+ return rv;
+
+ if (!ssl_config_.tls_username.empty() &&
+ !ssl_config_.tls_password.empty()) {
+ LOG(WARNING) << "Using TLS-SRP as " <<
+ ssl_config_.tls_username << " / " << ssl_config_.tls_password;
+
+ rv = SSL_SetUserLogin(nss_fd_,
+ ssl_config_.tls_username.c_str(),
+ ssl_config_.tls_password.c_str());
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(net_log_, "SSL_SetUserLogin", "");
+ return ERR_UNEXPECTED;
+ }
+ } else
+ LOG(INFO) << "Using TLS-SRP with no username/password";
+ } else {
+ // Disable SRP ciphers.
+ // TODO(sqs): this disable step should only be called if the SRP cipher
+ // suites are on by default.
+ rv = SetCiphersForTLSAuth(false, false);
+ if (rv != OK)
+ return rv;
+ }
+
+ for (std::vector<uint16>::const_iterator it =
+ ssl_config_.disabled_cipher_suites.begin();
+ it != ssl_config_.disabled_cipher_suites.end(); ++it) {
+ // This will fail if the specified cipher is not implemented by NSS, but
+ // the failure is harmless.
+ SSL_CipherPrefSet(nss_fd_, *it, PR_FALSE);
+ }
+
rv = SSL_HandshakeCallback(nss_fd_, HandshakeCallback, this);
if (rv != SECSuccess) {
LogFailedNSSFunction(net_log_, "SSL_HandshakeCallback", "");
@@ -1044,6 +1081,35 @@ int SSLClientSocketNSS::InitializeSSLOptions() {
return OK;
}
+// Enables SRP ciphers if |set_srp_ciphers| is true; otherwise, disables SRP
+// ciphers. If |disable_non_srp_ciphers| is true, then disable non-SRP ciphers;
+// otherwise, leave them alone.
+int SSLClientSocketNSS::SetCiphersForTLSAuth(bool set_srp_ciphers,
+ bool disable_non_srp_ciphers) {
+ int rv;
+ const PRUint16 *cipherSuites = SSL_GetImplementedCiphers();
+ int numCiphers = SSL_GetNumImplementedCiphers();
+ SSLCipherSuiteInfo info;
+ for (int i = 0; i < numCiphers; i++) {
+ PRUint16 suite = cipherSuites[i];
+ rv = SSL_GetCipherSuiteInfo(suite, &info, sizeof(info));
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(net_log_, "SSL_GetCipherSuiteInfo", "");
+ return ERR_UNEXPECTED;
+ }
+ if (IsNSSCipherKEATypeSRP(info.keaType)) {
+ rv = SSL_CipherPrefSet(nss_fd_, suite, set_srp_ciphers);
+ } else if (disable_non_srp_ciphers) {
+ rv = SSL_CipherPrefSet(nss_fd_, suite, PR_FALSE);
+ }
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(net_log_, "SSL_CipherPrefSet", "");
+ return ERR_UNEXPECTED;
+ }
+ }
+ return OK;
+}
+
int SSLClientSocketNSS::InitializeSSLPeerName() {
// Tell NSS who we're connected to
AddressList peer_address;
@@ -1096,6 +1162,43 @@ X509Certificate *SSLClientSocketNSS::UpdateServerCert() {
return server_cert_;
}
+// Sets tls_username_ and server_cert_needed_.
+void SSLClientSocketNSS::UpdateAuth() {
+ if (ssl_config_.use_tls_auth) {
+ // Get the username that we actually authenticated with.
+ SECItem user;
+ SECStatus rv = SSL_GetChannelUsername(nss_fd_, &user);
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(net_log_, "SSL_GetChannelUsername", "");
+ } else {
+ authenticated_tls_username_.assign(const_cast<char *>((char *)user.data),
+ (size_t)user.len);
+ SECITEM_FreeItem(&user, PR_FALSE);
+ }
+ DCHECK(authenticated_tls_username_ == ssl_config_.tls_username);
+
+ // See whether this SRP cipher suite uses certs.
+ SSLChannelInfo channel_info;
+ SSLCipherSuiteInfo info;
+ rv = SSL_GetChannelInfo(nss_fd_, &channel_info, sizeof(channel_info));
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(net_log_, "SSL_GetChannelInfo", "");
+ return;
+ }
+ if (!channel_info.cipherSuite) {
+ LOG(WARNING) << "Couldn't get SSL channel cipher suite";
+ return;
+ }
+ rv = SSL_GetCipherSuiteInfo(channel_info.cipherSuite, &info, sizeof(info));
+ if (rv != SECSuccess) {
+ LogFailedNSSFunction(net_log_, "SSL_GetCipherSuiteInfo", "");
+ return;
+ }
+ bool cipher_is_srp_no_certs = (info.keaType == ssl_kea_srp);
+ server_cert_needed_ = !cipher_is_srp_no_certs;
+ }
+}
+
// Sets ssl_connection_status_.
void SSLClientSocketNSS::UpdateConnectionStatus() {
SSLChannelInfo channel_info;
@@ -1449,6 +1552,8 @@ int SSLClientSocketNSS::DoSnapStartWaitForWrite() {
return OK;
}
+// TODO(sqs): this hangs if the server returns an unknown_psk_identity alert
+// that is not fatal (that is a warning)
int SSLClientSocketNSS::DoHandshake() {
EnterFunction("");
int net_error = net::OK;
@@ -1640,6 +1745,13 @@ int SSLClientSocketNSS::DoVerifyDNSSECComplete(int result) {
}
int SSLClientSocketNSS::DoVerifyCert(int result) {
+ if (!server_cert_needed_) {
+ DCHECK(ssl_config_.use_tls_auth);
+ DCHECK(!ssl_config_.tls_username.empty());
+ GotoState(STATE_VERIFY_CERT_COMPLETE);
+ return OK;
+ }
+
DCHECK(server_cert_);
GotoState(STATE_VERIFY_CERT_COMPLETE);
@@ -1809,16 +1921,20 @@ int SSLClientSocketNSS::DoPayloadWrite() {
void SSLClientSocketNSS::LogConnectionTypeMetrics() const {
UpdateConnectionTypeHistograms(CONNECTION_SSL);
- if (server_cert_verify_result_->has_md5)
- UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5);
- if (server_cert_verify_result_->has_md2)
- UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2);
- if (server_cert_verify_result_->has_md4)
- UpdateConnectionTypeHistograms(CONNECTION_SSL_MD4);
- if (server_cert_verify_result_->has_md5_ca)
- UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5_CA);
- if (server_cert_verify_result_->has_md2_ca)
- UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2_CA);
+
+ if (server_cert_verify_result_) {
+ if (server_cert_verify_result_->has_md5)
+ UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5);
+ if (server_cert_verify_result_->has_md2)
+ UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2);
+ if (server_cert_verify_result_->has_md4)
+ UpdateConnectionTypeHistograms(CONNECTION_SSL_MD4);
+ if (server_cert_verify_result_->has_md5_ca)
+ UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5_CA);
+ if (server_cert_verify_result_->has_md2_ca)
+ UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2_CA);
+ }
+
int ssl_version = SSLConnectionStatusToVersion(ssl_connection_status_);
switch (ssl_version) {
case SSL_CONNECTION_VERSION_SSL2:
@@ -1837,6 +1953,9 @@ void SSLClientSocketNSS::LogConnectionTypeMetrics() const {
UpdateConnectionTypeHistograms(CONNECTION_SSL_TLS1_2);
break;
};
+
+ if (!authenticated_tls_username_.empty())
+ UpdateConnectionTypeHistograms(CONNECTION_TLS_PASSWORD_AUTH);
}
// SaveSnapStartInfo extracts the information needed to perform a Snap Start
@@ -2495,6 +2614,7 @@ void SSLClientSocketNSS::HandshakeCallback(PRFileDesc* socket,
that->handshake_callback_called_ = true;
that->UpdateServerCert();
+ that->UpdateAuth();
that->UpdateConnectionStatus();
}
« no previous file with comments | « net/socket/ssl_client_socket_nss.h ('k') | net/socket/ssl_client_socket_tls_srp_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698