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

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: Add UMA logging of Token Binding support and NetLog event for Token Binding key lookup Created 5 years, 1 month 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 8a8e7421e4bbd5d3e8f5390f3fd5f601c176b45d..90098eda064a823f948a8802079a1c765e4cd14e 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -7,6 +7,7 @@
#include <set>
#include <vector>
+#include "base/base64.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/compiler_specific.h"
@@ -60,6 +61,7 @@
#include "net/spdy/spdy_session_pool.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/ssl/ssl_connection_status_flags.h"
+#include "net/ssl/token_binding.h"
#include "url/gurl.h"
#include "url/url_canon.h"
@@ -198,6 +200,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)
@@ -614,6 +621,48 @@ 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;
+}
+
+void HttpNetworkTransaction::RecordTokenBindingSupport() const {
+ enum {
+ DISABLED = 0,
+ CLIENT_ONLY = 1,
+ CLIENT_AND_SERVER = 2,
+ CLIENT_NO_CHANNEL_ID_SERVICE = 3,
+ UNSUPPORTED_KEY_PARAM = 4,
+ 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_key_param != TB_PARAM_ECDSAP256) {
+ supported = UNSUPPORTED_KEY_PARAM;
davidben 2015/11/18 20:49:00 This can never happen, no? You'll only negotiate t
nharper 2015/12/04 01:42:19 My thought here was if the server can negotiate to
+ } else if (ssl_info.token_binding_negotiated) {
+ supported = CLIENT_AND_SERVER;
+ } else {
+ supported = CLIENT_ONLY;
+ }
+ UMA_HISTOGRAM_ENUMERATION("TokenBinding.Support", supported,
+ TOKEN_BINDING_SUPPORT_MAX);
+}
+
bool HttpNetworkTransaction::UsingHttpProxyWithoutTunnel() const {
return (proxy_info_.is_http() || proxy_info_.is_https() ||
proxy_info_.is_quic()) &&
@@ -676,6 +725,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();
@@ -891,7 +947,34 @@ 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_,
+ base::Bind(&HttpNetworkTransaction::OnIOComplete, base::Unretained(this)),
davidben 2015/11/18 20:49:00 io_callback_
nharper 2015/12/04 01:42:19 Done.
+ &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 2015/11/18 20:49:00 Is this possible?
nharper 2015/12/04 01:42:19 I can't see how this would be possible (GetOrCreat
+
+ net_log_.EndEventWithNetErrorCode(
+ NetLog::TYPE_HTTP_TRANSACTION_GET_TOKEN_BINDING_KEY, rv);
return rv;
}
@@ -928,6 +1011,15 @@ void HttpNetworkTransaction::BuildRequestHeaders(
request_headers_.SetHeader(HttpRequestHeaders::kContentLength, "0");
}
+ RecordTokenBindingSupport();
+ if (token_binding_key_) {
davidben 2015/11/18 20:49:00 An HttpNetworkSession may run through a request mu
nharper 2015/12/04 01:42:19 Done.
+ std::string token_binding_header = BuildTokenBindingHeader();
+ if (token_binding_header != "") {
+ 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");
@@ -954,6 +1046,25 @@ void HttpNetworkTransaction::BuildRequestHeaders(
request_headers_.HasHeader(HttpRequestHeaders::kProxyAuthorization);
}
+std::string HttpNetworkTransaction::BuildTokenBindingHeader() {
+ std::string provided_token_binding;
+ int rv = stream_->GetProvidedTokenBindingWithKey(token_binding_key_,
+ &provided_token_binding);
+ if (rv != OK)
+ return "";
davidben 2015/11/18 20:49:00 If this or below fails, it should probably be fata
nharper 2015/12/04 01:42:19 Done.
+ std::vector<std::string> token_bindings;
+ token_bindings.push_back(provided_token_binding);
+ std::string header;
+ rv = BuildTokenBindingMessageFromTokenBindings(token_bindings, &header);
+ if (rv != OK)
+ return "";
+ std::string base64_header;
+ base::Base64Encode(header, &base64_header);
+ base::ReplaceChars(base64_header, "+", "-", &base64_header);
+ base::ReplaceChars(base64_header, "/", "_", &base64_header);
davidben 2015/11/18 20:49:00 base/base64url.h
nharper 2015/12/04 01:42:19 Done.
+ return base64_header;
+}
+
int HttpNetworkTransaction::DoInitRequestBody() {
next_state_ = STATE_INIT_REQUEST_BODY_COMPLETE;
int rv = OK;

Powered by Google App Engine
This is Rietveld 408576698