system-proxy: Request credentials from browser
When a ProxyConnectJob fails with "proxy auth required", the job will
ask for credentials from the ServerProxy object which owns it.
If the credentials are in the ServerProxy auth cache, the request will
be resolved with those credentials.
If not, the request will be forwarded to the parent process which will
send a dbus call to the browser to notify that it needs credentials for
a specific protection space (proxy_url, scheme, realm).
The browser will then send credentials along with the protection space
via dbus, with empty username and password if the user hasn't entered
them yet.
The dbus response is then forwarded to the ProxyConnectJob which made
the original request.
BUG=chromium:1042642
TEST=unittest
Change-Id: I1f5d43971d18df98aeb7c0b25642ceb29c761915
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2245699
Reviewed-by: Pavol Marko <pmarko@chromium.org>
Tested-by: Andreea-Elena Costinas <acostinas@google.com>
Commit-Queue: Andreea-Elena Costinas <acostinas@google.com>
diff --git a/system-proxy/server_proxy_test.cc b/system-proxy/server_proxy_test.cc
index f6dbd3c..4da1972 100644
--- a/system-proxy/server_proxy_test.cc
+++ b/system-proxy/server_proxy_test.cc
@@ -304,4 +304,136 @@
EXPECT_EQ(0, server_proxy_->pending_proxy_resolution_requests_.size());
}
+// This test verifies that the athentication request is forwarded to the parent
+// process and that the pending authentication requests are resolved when the
+// parent sends the credentials associated with the protection space included in
+// the request.
+TEST_F(ServerProxyTest, HandlePendingAuthRequests) {
+ RedirectStdPipes();
+
+ worker::ProtectionSpace protection_space;
+ protection_space.set_origin(kFakeProxyAddress);
+ protection_space.set_scheme("Basic");
+ protection_space.set_realm("Proxy test realm");
+ std::string actual_credentials = "";
+
+ EXPECT_CALL(*server_proxy_, GetStdoutPipe())
+ .WillOnce(Return(stdout_write_fd_.get()));
+
+ server_proxy_->AuthenticationRequired(
+ protection_space.origin(), protection_space.scheme(),
+ protection_space.realm(),
+ base::Bind(
+ [](std::string* actual_credentials, const std::string& credentials) {
+ *actual_credentials = credentials;
+ },
+ &actual_credentials));
+
+ EXPECT_EQ(1, server_proxy_->pending_auth_required_requests_.size());
+ EXPECT_EQ(protection_space.SerializeAsString(),
+ server_proxy_->pending_auth_required_requests_.begin()->first);
+
+ brillo_loop_.RunOnce(false);
+
+ worker::WorkerRequest request;
+ // Read the request from the worker's stdout output.
+ ASSERT_TRUE(ReadProtobuf(stdout_read_fd_.get(), &request));
+ ASSERT_TRUE(request.has_auth_required_request());
+ ASSERT_TRUE(request.auth_required_request().has_protection_space());
+ EXPECT_EQ(
+ request.auth_required_request().protection_space().SerializeAsString(),
+ protection_space.SerializeAsString());
+
+ // Write reply with a fake credentials to the worker's standard input.
+ worker::Credentials credentials;
+ *credentials.mutable_protection_space() = protection_space;
+ credentials.set_username("test_user");
+ credentials.set_password("test_pwd");
+ worker::WorkerConfigs configs;
+ *configs.mutable_credentials() = credentials;
+
+ ASSERT_TRUE(WriteProtobuf(stdin_write_fd_.get(), configs));
+ brillo_loop_.RunOnce(false);
+ EXPECT_EQ(0, server_proxy_->pending_auth_required_requests_.size());
+ EXPECT_EQ("test_user:test_pwd", actual_credentials);
+}
+
+// This test verifies that pending athentication requests are solved when the
+// parent returns empty credentials for the protection space.
+TEST_F(ServerProxyTest, HandlePendingAuthRequestsNoCredentials) {
+ RedirectStdPipes();
+
+ worker::ProtectionSpace protection_space;
+ protection_space.set_origin(kFakeProxyAddress);
+ protection_space.set_scheme("Basic");
+ protection_space.set_realm("Proxy test realm");
+ std::string actual_credentials = "";
+
+ EXPECT_CALL(*server_proxy_, GetStdoutPipe())
+ .WillOnce(Return(stdout_write_fd_.get()));
+
+ server_proxy_->AuthenticationRequired(
+ protection_space.origin(), protection_space.scheme(),
+ protection_space.realm(),
+ base::Bind(
+ [](std::string* actual_credentials, const std::string& credentials) {
+ *actual_credentials = credentials;
+ },
+ &actual_credentials));
+
+ EXPECT_EQ(1, server_proxy_->pending_auth_required_requests_.size());
+ EXPECT_EQ(protection_space.SerializeAsString(),
+ server_proxy_->pending_auth_required_requests_.begin()->first);
+
+ brillo_loop_.RunOnce(false);
+
+ worker::WorkerRequest request;
+ // Read the request from the worker's stdout output.
+ ASSERT_TRUE(ReadProtobuf(stdout_read_fd_.get(), &request));
+ ASSERT_TRUE(request.has_auth_required_request());
+ ASSERT_TRUE(request.auth_required_request().has_protection_space());
+ EXPECT_EQ(
+ request.auth_required_request().protection_space().SerializeAsString(),
+ protection_space.SerializeAsString());
+
+ // Write reply with a fake credentials to the worker's standard input.
+ worker::Credentials credentials;
+ *credentials.mutable_protection_space() = protection_space;
+ worker::WorkerConfigs configs;
+ *configs.mutable_credentials() = credentials;
+
+ ASSERT_TRUE(WriteProtobuf(stdin_write_fd_.get(), configs));
+ brillo_loop_.RunOnce(false);
+ EXPECT_EQ(0, server_proxy_->pending_auth_required_requests_.size());
+ EXPECT_EQ("", actual_credentials);
+}
+
+// This test verifies that the athentication request is solved with cached
+// credentials.
+TEST_F(ServerProxyTest, HandlePendingAuthRequestsCachedCredentials) {
+ RedirectStdPipes();
+
+ worker::ProtectionSpace protection_space;
+ protection_space.set_origin(kFakeProxyAddress);
+ protection_space.set_scheme("Basic");
+ protection_space.set_realm("Proxy test realm");
+ std::string actual_credentials = "";
+
+ server_proxy_->auth_cache_[protection_space.SerializeAsString()] =
+ "test_user:test_pwd";
+
+ server_proxy_->AuthenticationRequired(
+ protection_space.origin(), protection_space.scheme(),
+ protection_space.realm(),
+ base::Bind(
+ [](std::string* actual_credentials, const std::string& credentials) {
+ *actual_credentials = credentials;
+ },
+ &actual_credentials));
+
+ brillo_loop_.RunOnce(false);
+ EXPECT_EQ(0, server_proxy_->pending_auth_required_requests_.size());
+ EXPECT_EQ("test_user:test_pwd", actual_credentials);
+}
+
} // namespace system_proxy