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

Unified Diff: net/http/http_network_transaction.cc

Issue 1378613004: Set Token-Binding HTTP header (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@tb-tls-ext-new
Patch Set: fix build issues Created 4 years, 11 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
Index: net/http/http_network_transaction.cc
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index 201e3915a24f7c637cd382906ce8d7fdbb0fa1d0..1d56d28fe1c81811d8cecaecbdfddef561d0a69f 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -8,6 +8,7 @@
#include <utility>
#include <vector>
+#include "base/base64url.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/compiler_specific.h"
@@ -62,6 +63,7 @@
#include "net/ssl/ssl_cert_request_info.h"
#include "net/ssl/ssl_connection_status_flags.h"
#include "net/ssl/ssl_private_key.h"
+#include "net/ssl/token_binding.h"
#include "url/gurl.h"
#include "url/url_canon.h"
@@ -201,6 +203,11 @@ int HttpNetworkTransaction::Start(const HttpRequestInfo* request_info,
if (request_->privacy_mode == PRIVACY_MODE_ENABLED)
server_ssl_config_.channel_id_enabled = false;
+ if (session_->params().enable_token_binding &&
+ session_->params().channel_id_service) {
+ server_ssl_config_.token_binding_params.push_back(TB_PARAM_ECDSAP256);
+ }
+
next_state_ = STATE_NOTIFY_BEFORE_CREATE_STREAM;
int rv = DoLoop(OK);
if (rv == ERR_IO_PENDING)
@@ -639,6 +646,45 @@ bool HttpNetworkTransaction::IsSecureRequest() const {
return request_->url.SchemeIsCryptographic();
}
+bool HttpNetworkTransaction::IsTokenBindingEnabled() const {
+ if (!IsSecureRequest())
+ return false;
+ SSLInfo ssl_info;
+ stream_->GetSSLInfo(&ssl_info);
+ if (!ssl_info.token_binding_negotiated)
+ return false;
+ if (ssl_info.token_binding_key_param != TB_PARAM_ECDSAP256)
+ return false;
+ if (!session_->params().channel_id_service)
+ return false;
+ return true;
davidben 2016/01/22 00:19:20 Nit: You could also just write return ssl_info.
nharper 2016/01/22 19:36:51 If there's a bug in the code elsewhere, it's possi
+}
+
+void HttpNetworkTransaction::RecordTokenBindingSupport() const {
+ enum {
+ DISABLED = 0,
+ CLIENT_ONLY = 1,
+ CLIENT_AND_SERVER = 2,
+ CLIENT_NO_CHANNEL_ID_SERVICE = 3,
+ TOKEN_BINDING_SUPPORT_MAX
+ } supported;
+ if (!IsSecureRequest())
+ return;
+ SSLInfo ssl_info;
+ stream_->GetSSLInfo(&ssl_info);
+ if (!session_->params().enable_token_binding) {
+ supported = DISABLED;
+ } else if (!session_->params().channel_id_service) {
+ supported = CLIENT_NO_CHANNEL_ID_SERVICE;
+ } else if (ssl_info.token_binding_negotiated) {
+ supported = CLIENT_AND_SERVER;
+ } else {
+ supported = CLIENT_ONLY;
+ }
+ UMA_HISTOGRAM_ENUMERATION("Net.TokenBinding.Support", supported,
+ TOKEN_BINDING_SUPPORT_MAX);
+}
+
bool HttpNetworkTransaction::UsingHttpProxyWithoutTunnel() const {
return (proxy_info_.is_http() || proxy_info_.is_https() ||
proxy_info_.is_quic()) &&
@@ -701,6 +747,13 @@ int HttpNetworkTransaction::DoLoop(int result) {
case STATE_GENERATE_SERVER_AUTH_TOKEN_COMPLETE:
rv = DoGenerateServerAuthTokenComplete(rv);
break;
+ case STATE_GET_TOKEN_BINDING_KEY:
+ DCHECK_EQ(OK, rv);
+ rv = DoGetTokenBindingKey();
+ break;
+ case STATE_GET_TOKEN_BINDING_KEY_COMPLETE:
+ rv = DoGetTokenBindingKeyComplete(rv);
+ break;
case STATE_INIT_REQUEST_BODY:
DCHECK_EQ(OK, rv);
rv = DoInitRequestBody();
@@ -916,11 +969,37 @@ int HttpNetworkTransaction::DoGenerateServerAuthToken() {
int HttpNetworkTransaction::DoGenerateServerAuthTokenComplete(int rv) {
DCHECK_NE(ERR_IO_PENDING, rv);
if (rv == OK)
- next_state_ = STATE_INIT_REQUEST_BODY;
+ next_state_ = STATE_GET_TOKEN_BINDING_KEY;
+ return rv;
+}
+
+int HttpNetworkTransaction::DoGetTokenBindingKey() {
+ next_state_ = STATE_GET_TOKEN_BINDING_KEY_COMPLETE;
+ if (!IsTokenBindingEnabled())
+ return OK;
+
+ net_log_.BeginEvent(NetLog::TYPE_HTTP_TRANSACTION_GET_TOKEN_BINDING_KEY);
+ ChannelIDService* channel_id_service = session_->params().channel_id_service;
+ return channel_id_service->GetOrCreateChannelID(
+ request_->url.host(), &token_binding_key_, io_callback_,
+ &token_binding_request_);
+}
+
+int HttpNetworkTransaction::DoGetTokenBindingKeyComplete(int rv) {
+ DCHECK_NE(ERR_IO_PENDING, rv);
+ next_state_ = STATE_INIT_REQUEST_BODY;
+ if (!IsTokenBindingEnabled())
+ return OK;
+
+ if (rv == OK && !token_binding_key_)
+ rv = ERR_CHANNEL_ID_IMPORT_FAILED;
davidben 2016/01/22 00:19:20 Pfft. Apparently this dates to https://codereview.
nharper 2016/01/22 19:36:51 This statement is now removed.
+
+ net_log_.EndEventWithNetErrorCode(
+ NetLog::TYPE_HTTP_TRANSACTION_GET_TOKEN_BINDING_KEY, rv);
return rv;
}
-void HttpNetworkTransaction::BuildRequestHeaders(
+int HttpNetworkTransaction::BuildRequestHeaders(
bool using_http_proxy_without_tunnel) {
request_headers_.SetHeader(HttpRequestHeaders::kHost,
GetHostAndOptionalPort(request_->url));
@@ -953,6 +1032,16 @@ void HttpNetworkTransaction::BuildRequestHeaders(
request_headers_.SetHeader(HttpRequestHeaders::kContentLength, "0");
}
+ RecordTokenBindingSupport();
+ if (token_binding_key_) {
+ std::string token_binding_header;
+ int rv = BuildTokenBindingHeader(&token_binding_header);
+ if (rv != OK)
+ return rv;
+ request_headers_.SetHeader(HttpRequestHeaders::kTokenBinding,
+ token_binding_header);
+ }
+
// Honor load flags that impact proxy caches.
if (request_->load_flags & LOAD_BYPASS_CACHE) {
request_headers_.SetHeader(HttpRequestHeaders::kPragma, "no-cache");
@@ -977,6 +1066,29 @@ void HttpNetworkTransaction::BuildRequestHeaders(
response_.did_use_http_auth =
request_headers_.HasHeader(HttpRequestHeaders::kAuthorization) ||
request_headers_.HasHeader(HttpRequestHeaders::kProxyAuthorization);
+ return OK;
+}
+
+int HttpNetworkTransaction::BuildTokenBindingHeader(std::string* out) {
+ std::vector<uint8_t> signed_ekm;
+ int rv = stream_->GetSignedEKMForTokenBinding(token_binding_key_.get(),
+ &signed_ekm);
+ if (rv != OK)
+ return rv;
+ std::string provided_token_binding;
+ rv = BuildProvidedTokenBinding(token_binding_key_.get(), signed_ekm,
+ &provided_token_binding);
+ if (rv != OK)
+ return rv;
+ std::vector<base::StringPiece> token_bindings;
+ token_bindings.push_back(provided_token_binding);
+ std::string header;
+ rv = BuildTokenBindingMessageFromTokenBindings(token_bindings, &header);
davidben 2016/01/22 00:19:20 You could probably fold this and BuildProvidedToke
nharper 2016/01/22 19:36:52 Once we support the federated use case (i.e. refer
+ if (rv != OK)
+ return rv;
+ base::Base64UrlEncode(header, base::Base64UrlEncodePolicy::INCLUDE_PADDING,
+ out);
+ return OK;
}
int HttpNetworkTransaction::DoInitRequestBody() {
@@ -1001,7 +1113,7 @@ int HttpNetworkTransaction::DoBuildRequest() {
// we have proxy info available.
if (request_headers_.IsEmpty()) {
bool using_http_proxy_without_tunnel = UsingHttpProxyWithoutTunnel();
- BuildRequestHeaders(using_http_proxy_without_tunnel);
+ return BuildRequestHeaders(using_http_proxy_without_tunnel);
}
return OK;
@@ -1486,6 +1598,7 @@ void HttpNetworkTransaction::ResetStateForAuthRestart() {
remote_endpoint_ = IPEndPoint();
net_error_details_.quic_broken = false;
net_error_details_.quic_connection_error = QUIC_NO_ERROR;
+ token_binding_key_.reset();
}
void HttpNetworkTransaction::CacheNetErrorDetailsAndResetStream() {

Powered by Google App Engine
This is Rietveld 408576698