From: Francis Dupont Date: Tue, 28 Jul 2020 14:26:42 +0000 (+0200) Subject: [#1304] Prepared server callout X-Git-Tag: Kea-1.9.0~138 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f3ed57a5ed26c7fa38e015d3871b39bca32900f3;p=thirdparty%2Fkea.git [#1304] Prepared server callout --- diff --git a/src/bin/agent/ca_response_creator.cc b/src/bin/agent/ca_response_creator.cc index c102157f21..75fb93b6cd 100644 --- a/src/bin/agent/ca_response_creator.cc +++ b/src/bin/agent/ca_response_creator.cc @@ -83,12 +83,9 @@ createDynamicHttpResponse(const ConstHttpRequestPtr& request) { if (ctx) { const BasicHttpAuthConfig& auth = ctx->getBasicAuthConfig(); const BasicHttpAuthMap& auth_map = auth.getCredentialMap(); - // Check authentication when required. - if (!auth_map.empty()) { - http_response = - checkBasicHttpAuth(*this, request, auth_map, - ctx->getBasicAuthRealm()); - } + // Check authentication. + http_response = checkAuth(*this, request, auth_map, + ctx->getBasicAuthRealm()); } } } diff --git a/src/lib/http/response_creator_auth.cc b/src/lib/http/response_creator_auth.cc index 3b278ddb04..4a19c14008 100644 --- a/src/lib/http/response_creator_auth.cc +++ b/src/lib/http/response_creator_auth.cc @@ -17,11 +17,14 @@ using namespace std; namespace isc { namespace http { -HttpResponseJsonPtr checkBasicHttpAuth(const HttpResponseCreator& creator, - const ConstHttpRequestPtr& request, - const BasicHttpAuthMap& credentials, - const std::string& realm) { - try { +HttpResponseJsonPtr checkAuth(const HttpResponseCreator& creator, + const ConstHttpRequestPtr& request, + const BasicHttpAuthMap& credentials, + const std::string& realm) { + bool authentic = false; + if (credentials.empty()) { + authentic = true; + } else try { string value = request->getHeaderValue("Authorization"); // Trim space characters. value = str::trim(value); @@ -43,21 +46,27 @@ HttpResponseJsonPtr checkBasicHttpAuth(const HttpResponseCreator& creator, LOG_DEBUG(http_logger, isc::log::DBGLVL_TRACE_BASIC, HTTP_CLIENT_REQUEST_AUTHORIZED) .arg(it->second); - return (HttpResponseJsonPtr()); + authentic = true; + } else { + LOG_INFO(http_logger, HTTP_CLIENT_REQUEST_NOT_AUTHORIZED); + authentic = false; } - LOG_INFO(http_logger, HTTP_CLIENT_REQUEST_NOT_AUTHORIZED); } catch (const HttpMessageNonExistingHeader&) { LOG_INFO(http_logger, HTTP_CLIENT_REQUEST_NO_AUTH_HEADER); } catch (const BadValue& ex) { LOG_INFO(http_logger, HTTP_CLIENT_REQUEST_BAD_AUTH_HEADER) .arg(ex.what()); } + if (authentic) { + return (HttpResponseJsonPtr()); + } + string scheme = "Basic"; HttpResponsePtr response = creator.createStockHttpResponse(request, HttpStatusCode::UNAUTHORIZED); response->reset(); response->context()->headers_.push_back( HttpHeaderContext("WWW-Authenticate", - "Basic realm=\"" + realm + "\"")); + scheme + " realm=\"" + realm + "\"")); response->finalize(); return (boost::dynamic_pointer_cast(response)); } diff --git a/src/lib/http/response_creator_auth.h b/src/lib/http/response_creator_auth.h index 830b335f6b..26e1c1aca3 100644 --- a/src/lib/http/response_creator_auth.h +++ b/src/lib/http/response_creator_auth.h @@ -16,17 +16,21 @@ namespace isc { namespace http { -/// @brief Validate basic HTTP authentication. +/// @brief Validate authentication. +/// +/// Currently it only validates basic HTTP authentication. +/// Empty credentials map means that basic HTTP authentication is +/// not required i.e. all requests validate. /// /// @param creator The HTTP response creator. /// @param request The HTTP request to validate. /// @param credentials A map of all allowed credentials. /// @param realm Realm name. /// @return Error HTTP response if validation failed, null otherwise. -HttpResponseJsonPtr checkBasicHttpAuth(const HttpResponseCreator& creator, - const ConstHttpRequestPtr& request, - const BasicHttpAuthMap& credentials, - const std::string& realm); +HttpResponseJsonPtr checkAuth(const HttpResponseCreator& creator, + const ConstHttpRequestPtr& request, + const BasicHttpAuthMap& credentials, + const std::string& realm); } // end of namespace isc::http } // end of namespace isc diff --git a/src/lib/http/tests/response_creator_unittests.cc b/src/lib/http/tests/response_creator_unittests.cc index e32f60dcbd..35836c22eb 100644 --- a/src/lib/http/tests/response_creator_unittests.cc +++ b/src/lib/http/tests/response_creator_unittests.cc @@ -109,6 +109,9 @@ TEST(HttpResponseCreatorTest, badRequest) { // This test verifies that response is generated successfully from the // finalized/parsed request. TEST(HttpResponseCreatorTest, goodRequest) { + // There is no credentials so it checks also what happens when + // authentication is not required. + HttpResponsePtr response; // Create request and finalize it. HttpRequestPtr request(new HttpRequest()); @@ -137,6 +140,14 @@ class HttpResponseCreatorAuthTest : public LogContentTest { }; // This test verifies that missing required authentication header gives // unauthorized error. TEST_F(HttpResponseCreatorAuthTest, noAuth) { + // Create credentials. + BasicHttpAuthPtr basic_auth; + EXPECT_NO_THROW(basic_auth.reset(new BasicHttpAuth("test", "123\xa3"))); + EXPECT_EQ("dGVzdDoxMjPCow==", basic_auth->getCredential()); + BasicHttpAuthMap credentials; + credentials[basic_auth->getCredential()] = "test"; + string realm = "ISC.ORG"; + // Create request and finalize it. HttpRequestPtr request(new HttpRequest()); request->context()->http_version_major_ = 1; @@ -147,11 +158,7 @@ TEST_F(HttpResponseCreatorAuthTest, noAuth) { HttpResponsePtr response; TestHttpResponseCreatorPtr creator(new TestHttpResponseCreator());; - BasicHttpAuthMap credentials; - string realm = "ISC.ORG"; - - ASSERT_NO_THROW(response = - checkBasicHttpAuth(*creator, request, credentials, realm)); + ASSERT_NO_THROW(response = checkAuth(*creator, request, credentials, realm)); ASSERT_TRUE(response); EXPECT_EQ("HTTP/1.0 401 Unauthorized\r\n" @@ -169,6 +176,14 @@ TEST_F(HttpResponseCreatorAuthTest, noAuth) { // This test verifies that too short authentication header is rejected. TEST_F(HttpResponseCreatorAuthTest, authTooShort) { + // Create credentials. + BasicHttpAuthPtr basic_auth; + EXPECT_NO_THROW(basic_auth.reset(new BasicHttpAuth("test", "123\xa3"))); + EXPECT_EQ("dGVzdDoxMjPCow==", basic_auth->getCredential()); + BasicHttpAuthMap credentials; + credentials[basic_auth->getCredential()] = "test"; + string realm = "ISC.ORG"; + // Create request and finalize it. HttpRequestPtr request(new HttpRequest()); request->context()->http_version_major_ = 1; @@ -181,11 +196,7 @@ TEST_F(HttpResponseCreatorAuthTest, authTooShort) { HttpResponsePtr response; TestHttpResponseCreatorPtr creator(new TestHttpResponseCreator());; - BasicHttpAuthMap credentials; - string realm = "ISC.ORG"; - - ASSERT_NO_THROW(response = - checkBasicHttpAuth(*creator, request, credentials, realm)); + ASSERT_NO_THROW(response = checkAuth(*creator, request, credentials, realm)); ASSERT_TRUE(response); EXPECT_EQ("HTTP/1.0 401 Unauthorized\r\n" @@ -204,6 +215,14 @@ TEST_F(HttpResponseCreatorAuthTest, authTooShort) { // This test verifies that another authentication schema is rejected. TEST_F(HttpResponseCreatorAuthTest, badScheme) { + // Create credentials. + BasicHttpAuthPtr basic_auth; + EXPECT_NO_THROW(basic_auth.reset(new BasicHttpAuth("test", "123\xa3"))); + EXPECT_EQ("dGVzdDoxMjPCow==", basic_auth->getCredential()); + BasicHttpAuthMap credentials; + credentials[basic_auth->getCredential()] = "test"; + string realm = "ISC.ORG"; + // Create request and finalize it. HttpRequestPtr request(new HttpRequest()); request->context()->http_version_major_ = 1; @@ -216,11 +235,7 @@ TEST_F(HttpResponseCreatorAuthTest, badScheme) { HttpResponsePtr response; TestHttpResponseCreatorPtr creator(new TestHttpResponseCreator());; - BasicHttpAuthMap credentials; - string realm = "ISC.ORG"; - - ASSERT_NO_THROW(response = - checkBasicHttpAuth(*creator, request, credentials, realm)); + ASSERT_NO_THROW(response = checkAuth(*creator, request, credentials, realm)); ASSERT_TRUE(response); EXPECT_EQ("HTTP/1.0 401 Unauthorized\r\n" @@ -239,23 +254,28 @@ TEST_F(HttpResponseCreatorAuthTest, badScheme) { // This test verifies that not matching credential is rejected. TEST_F(HttpResponseCreatorAuthTest, notMatching) { + // Create credentials. + BasicHttpAuthPtr basic_auth; + EXPECT_NO_THROW(basic_auth.reset(new BasicHttpAuth("test", "123\xa3"))); + EXPECT_EQ("dGVzdDoxMjPCow==", basic_auth->getCredential()); + BasicHttpAuthMap credentials; + credentials[basic_auth->getCredential()] = "test"; + string realm = "ISC.ORG"; + // Create request and finalize it. HttpRequestPtr request(new HttpRequest()); request->context()->http_version_major_ = 1; request->context()->http_version_minor_ = 0; request->context()->method_ = "GET"; request->context()->uri_ = "/foo"; - HttpHeaderContext auth("Authorization", "Basic dGVzdDoxMjPCow=="); + // Slightly different credential... + HttpHeaderContext auth("Authorization", "Basic dGvZdDoxMjPcOw=="); request->context()->headers_.push_back(auth); ASSERT_NO_THROW(request->finalize()); HttpResponsePtr response; TestHttpResponseCreatorPtr creator(new TestHttpResponseCreator());; - BasicHttpAuthMap credentials; - string realm = "ISC.ORG"; - - ASSERT_NO_THROW(response = - checkBasicHttpAuth(*creator, request, credentials, realm)); + ASSERT_NO_THROW(response = checkAuth(*creator, request, credentials, realm)); ASSERT_TRUE(response); EXPECT_EQ("HTTP/1.0 401 Unauthorized\r\n" @@ -273,27 +293,27 @@ TEST_F(HttpResponseCreatorAuthTest, notMatching) { // This test verifies that matching credential is accepted. TEST_F(HttpResponseCreatorAuthTest, matching) { + // Create credentials. + BasicHttpAuthPtr basic_auth; + EXPECT_NO_THROW(basic_auth.reset(new BasicHttpAuth("test", "123\xa3"))); + EXPECT_EQ("dGVzdDoxMjPCow==", basic_auth->getCredential()); + BasicHttpAuthMap credentials; + credentials[basic_auth->getCredential()] = "test"; + string realm = "ISC.ORG"; + // Create request and finalize it. HttpRequestPtr request(new HttpRequest()); request->context()->http_version_major_ = 1; request->context()->http_version_minor_ = 0; request->context()->method_ = "GET"; request->context()->uri_ = "/foo"; - BasicHttpAuthPtr basic_auth; - EXPECT_NO_THROW(basic_auth.reset(new BasicHttpAuth("test", "123\xa3"))); - EXPECT_EQ("dGVzdDoxMjPCow==", basic_auth->getCredential()); BasicAuthHttpHeaderContext auth(*basic_auth); request->context()->headers_.push_back(auth); ASSERT_NO_THROW(request->finalize()); HttpResponsePtr response; TestHttpResponseCreatorPtr creator(new TestHttpResponseCreator());; - BasicHttpAuthMap credentials; - credentials[basic_auth->getCredential()] = "test"; - string realm = "ISC.ORG"; - - ASSERT_NO_THROW(response = - checkBasicHttpAuth(*creator, request, credentials, realm)); + ASSERT_NO_THROW(response = checkAuth(*creator, request, credentials, realm)); EXPECT_FALSE(response); addString("HTTP_CLIENT_REQUEST_AUTHORIZED received HTTP request "