From 306d488efc2ee7f394a7c54fab1b6231b25029c8 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Fri, 10 Jul 2020 23:05:16 +0200 Subject: [PATCH 01/33] [#1304] Added latin1 -> UTF-8 encoder --- src/lib/util/Makefile.am | 4 ++- src/lib/util/encode/utf8.cc | 33 +++++++++++++++++++ src/lib/util/encode/utf8.h | 27 ++++++++++++++++ src/lib/util/tests/Makefile.am | 2 +- src/lib/util/tests/utf8_unittest.cc | 50 +++++++++++++++++++++++++++++ 5 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 src/lib/util/encode/utf8.cc create mode 100644 src/lib/util/encode/utf8.h create mode 100644 src/lib/util/tests/utf8_unittest.cc diff --git a/src/lib/util/Makefile.am b/src/lib/util/Makefile.am index adf6735f26..c8085603e7 100644 --- a/src/lib/util/Makefile.am +++ b/src/lib/util/Makefile.am @@ -42,6 +42,7 @@ libkea_util_la_SOURCES += encode/base32hex_from_binary.h libkea_util_la_SOURCES += encode/base_n.cc encode/hex.h libkea_util_la_SOURCES += encode/binary_from_base32hex.h libkea_util_la_SOURCES += encode/binary_from_base16.h +libkea_util_la_SOURCES += encode/utf8.cc encode/utf8.h libkea_util_la_SOURCES += random/qid_gen.h random/qid_gen.cc libkea_util_la_SOURCES += random/random_number_generator.h @@ -94,7 +95,8 @@ libkea_util_encode_include_HEADERS = \ encode/base64.h \ encode/binary_from_base16.h \ encode/binary_from_base32hex.h \ - encode/hex.h + encode/hex.h \ + encode/utf8.h libkea_util_io_includedir = $(pkgincludedir)/util/io libkea_util_io_include_HEADERS = \ diff --git a/src/lib/util/encode/utf8.cc b/src/lib/util/encode/utf8.cc new file mode 100644 index 0000000000..0c0aadf7e7 --- /dev/null +++ b/src/lib/util/encode/utf8.cc @@ -0,0 +1,33 @@ +// Copyright (C) 2020 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include + +namespace isc { +namespace util { +namespace encode { + +std::vector encodeUtf8(const std::string& value) { + std::vector result; + if (value.empty()) { + return (result); + } + const uint8_t* start = reinterpret_cast(value.c_str()); + std::vector binary(start, start + value.size()); + for (uint8_t ch : binary) { + if (ch < 0x80) { + result.push_back(ch); + } else { + result.push_back(0xc0 | (ch >> 6)); + result.push_back(0x80 | (ch & 0x3f)); + } + } + return (result); +} + +} // namespace encode +} // namespace util +} // namespace isc diff --git a/src/lib/util/encode/utf8.h b/src/lib/util/encode/utf8.h new file mode 100644 index 0000000000..9eda47175e --- /dev/null +++ b/src/lib/util/encode/utf8.h @@ -0,0 +1,27 @@ +// Copyright (C) 2020 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef UTF8_H +#define UTF8_H 1 + +#include +#include +#include + +namespace isc { +namespace util { +namespace encode { +/// @brief Encode value string into UTF-8. +/// +/// @param value A string in latin1 i.e. no encoding. +/// @return A vector object storing the data encoded in UTF-8. +std::vector encodeUtf8(const std::string& value); + +} // namespace encode +} // namespace util +} // namespace isc + +#endif // UTF8_H diff --git a/src/lib/util/tests/Makefile.am b/src/lib/util/tests/Makefile.am index b04d07278f..f5b3598f07 100644 --- a/src/lib/util/tests/Makefile.am +++ b/src/lib/util/tests/Makefile.am @@ -61,11 +61,11 @@ run_unittests_SOURCES += readwrite_mutex_unittest.cc run_unittests_SOURCES += signal_set_unittest.cc run_unittests_SOURCES += stopwatch_unittest.cc run_unittests_SOURCES += unlock_guard_unittests.cc +run_unittests_SOURCES += utf8_unittest.cc run_unittests_SOURCES += versioned_csv_file_unittest.cc run_unittests_SOURCES += watch_socket_unittests.cc run_unittests_SOURCES += watched_thread_unittest.cc - run_unittests_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_INCLUDES) run_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS) diff --git a/src/lib/util/tests/utf8_unittest.cc b/src/lib/util/tests/utf8_unittest.cc new file mode 100644 index 0000000000..168f38bba3 --- /dev/null +++ b/src/lib/util/tests/utf8_unittest.cc @@ -0,0 +1,50 @@ +// Copyright (C) 2020 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include + +#include + +#include + +using namespace isc::util; +using namespace isc::util::encode; +using namespace std; + +namespace { + +// Verify it does nothing for ASCII. +TEST(Utf8Test, foobar) { + string str("foobar"); + vector vec8 = encodeUtf8(str); + ASSERT_FALSE(vec8.empty()); + const char* start = reinterpret_cast(&vec8[0]); + string str8(start, start + vec8.size()); + EXPECT_EQ(str, str8); +} + +// Verify it encodes not ASCII as expected. +TEST(Utf8Test, eightc) { + string str("-\x8c-"); + vector vec8 = encodeUtf8(str); + ASSERT_FALSE(vec8.empty()); + const char* start = reinterpret_cast(&vec8[0]); + string str8(start, start + vec8.size()); + string expected("-\xc2\x8c-"); + EXPECT_EQ(expected, str8); +} + +// Verify it handles correctly control characters. +TEST(Utf8Test, control) { + string str("fo\x00\n\bar"); + vector vec8 = encodeUtf8(str); + ASSERT_FALSE(vec8.empty()); + const char* start = reinterpret_cast(&vec8[0]); + string str8(start, start + vec8.size()); + EXPECT_EQ(str, str8); +} + +} -- GitLab From ab45c213b72106429cc67653c3b7b7687ebe29e5 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Sat, 11 Jul 2020 01:15:06 +0200 Subject: [PATCH 02/33] [#1304] Checkpoint: updated shell + http basic_auth --- doc/sphinx/man/kea-shell.8.rst | 10 ++- src/bin/shell/kea-shell.in | 15 +++- src/bin/shell/kea-shell.rst | 10 +++ src/bin/shell/kea_conn.py | 8 ++- src/bin/shell/tests/shell_unittest.py.in | 34 ++++++++- src/lib/http/Makefile.am | 1 + src/lib/http/basic_auth.cc | 49 +++++++++++++ src/lib/http/basic_auth.h | 84 ++++++++++++++++++++++ src/lib/http/tests/Makefile.am | 3 +- src/lib/http/tests/basic_auth_unittests.cc | 55 ++++++++++++++ 10 files changed, 263 insertions(+), 6 deletions(-) create mode 100644 src/lib/http/basic_auth.cc create mode 100644 src/lib/http/basic_auth.h create mode 100644 src/lib/http/tests/basic_auth_unittests.cc diff --git a/doc/sphinx/man/kea-shell.8.rst b/doc/sphinx/man/kea-shell.8.rst index 00454a8f36..fb88cdc419 100644 --- a/doc/sphinx/man/kea-shell.8.rst +++ b/doc/sphinx/man/kea-shell.8.rst @@ -15,7 +15,7 @@ kea-shell - Text client for Control Agent process Synopsis ~~~~~~~~ -:program:`kea-shell` [**-h**] [**-v**] [**--host**] [**--port**] [**--path**] [**--timeout**] [**--service**] [command] +:program:`kea-shell` [**-h**] [**-v**] [**--host**] [**--port**] [**--path**] [**--auth-user**] [**--auth-password**] [**--timeout**] [**--service**] [command] Description ~~~~~~~~~~~ @@ -50,6 +50,14 @@ The arguments are as follows: path is used. As Control Agent listens at the empty path, this parameter is useful only with a reverse proxy. +``--auth-user`` + Specifies the user name for basic HTTP authentication. If not specified + or specified as the empty string authentication is not used. + +``--auth-password`` + Specifies the password for basic HTTP authentication. If not specified + but the user name is specified an empty password is used. + ``--timeout`` Specifies the connection timeout in seconds. If not specified, 10 (seconds) is used. diff --git a/src/bin/shell/kea-shell.in b/src/bin/shell/kea-shell.in index 18a1887bc9..d4fa02f101 100644 --- a/src/bin/shell/kea-shell.in +++ b/src/bin/shell/kea-shell.in @@ -1,6 +1,6 @@ #!@PYTHON@ -# Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2017-2020 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this @@ -21,6 +21,7 @@ import os import sys import signal import argparse +from base64 import b64encode sys.path.append('@PKGPYTHONDIR@') @@ -69,6 +70,10 @@ def shell_body(): parser.add_argument('--service', nargs="?", action="append", help='target spcified service. If not specified,' 'control agent will receive command.') + parser.add_argument('--auth-user', type=str, default='', + help='Basic HTTP authentication user') + parser.add_argument('--auth-password', type=str, default='', + help='Basic HTTP authentication password') parser.add_argument('command', type=str, nargs="?", default='list-commands', help='command to be executed. If not specified, ' @@ -88,6 +93,14 @@ def shell_body(): params.http_host = cmd_args.host params.http_port = cmd_args.port params.path += cmd_args.path + if cmd_args.auth_user is not '': + user = cmd_args.auth_user.encode('latin1') + password = cmd_args.auth_password.encode('latin1') + secret = b':'.join((user, password)) + if sys.version_info[0] == 3: + params.auth = b64encode(secret).strip().decode('ascii') + else: + params.auth = b64encode(secret).strip().encode('ascii') params.timeout = cmd_args.timeout params.version = VERSION diff --git a/src/bin/shell/kea-shell.rst b/src/bin/shell/kea-shell.rst index 51c9f2c808..6a721f9699 100644 --- a/src/bin/shell/kea-shell.rst +++ b/src/bin/shell/kea-shell.rst @@ -11,6 +11,8 @@ kea-shell --host --port --path +--auth-user +--auth-password --timeout --service command @@ -47,6 +49,14 @@ The arguments are as follows: path is used. As Control Agent listens at the empty path this parameter is useful only with a reverse proxy. +``--auth-user`` + Specifies the user name for basic HTTP authentication. If not specified + or specified as the empty string authentication is not used. + +``--auth-password`` + Specifies the password for basic HTTP authentication. If not specified + but the user name is specified an empty password is used. + ``--timeout`` Specifies the connection timeout in seconds. If not specified, 10 (seconds) is used. diff --git a/src/bin/shell/kea_conn.py b/src/bin/shell/kea_conn.py index ca4aafc8ae..d8c54aa48a 100644 --- a/src/bin/shell/kea_conn.py +++ b/src/bin/shell/kea_conn.py @@ -1,4 +1,4 @@ -# Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2017-2020 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this @@ -18,6 +18,7 @@ class CARequest: - command - specifies the command to send (e.g. list-commands) - service - specifies service that is target for the command (e.g. dhcp4) - timeout - timeout (in ms) + - auth - basic HTTP authentication credential - args - extra arguments my be added here - headers - extra HTTP headers may be added here - version - version to be reported in HTTP header @@ -28,6 +29,7 @@ class CARequest: command = '' service = '' timeout = 0 + auth = None args = '' headers = {} version = "" @@ -55,9 +57,11 @@ class CARequest: In particular, this method generates Content-Length and its value. """ - self.headers['Content-Type'] = 'application/json' self.headers['User-Agent'] = "Kea-shell/%s"%(self.version) self.headers['Accept'] = '*/*' + if self.auth is not None: + self.headers['Authorization'] = "Basic %s"%(self.auth) + self.headers['Content-Type'] = 'application/json' self.headers['Content-Length'] = "%d"%(len(self.content)) diff --git a/src/bin/shell/tests/shell_unittest.py.in b/src/bin/shell/tests/shell_unittest.py.in index 1fd6ec2003..74c320749f 100644 --- a/src/bin/shell/tests/shell_unittest.py.in +++ b/src/bin/shell/tests/shell_unittest.py.in @@ -1,6 +1,6 @@ #!@PYTHON@ -# Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2017-2020 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this @@ -11,6 +11,8 @@ Kea shell unittest (python part) """ import unittest +import sys +from base64 import b64encode from kea_conn import CARequest @@ -138,6 +140,36 @@ class CARequestUnitTest(unittest.TestCase): self.assertTrue(self.check_header(request.headers, 'User-Agent', 'Kea-shell/1.2.3')) + def test_basic_http_auth(self): + """ + This test check if the basic HTTP authentication credential + generated properly. + """ + user = 'foo' + password = 'bar' + buser = user.encode('latin1') + bpassword = password.encode('latin1') + secret = b':'.join((buser, bpassword)) + self.assertEqual(b'foo:bar', secret) + if sys.version_info[0] == 3: + auth = b64encode(secret).strip().decode('ascii') + else: + auth = b64encode(secret).strip().encode('ascii') + self.assertEqual('Zm9vOmJhcg==', auth) + + def test_header_auth(self): + """ + This test checks if the basic HTTP authentication header is + generated properly. + """ + request = CARequest() + request.auth = "Zm9vOmJhcg==" + request.generate_headers() + + self.assertTrue(self.check_header(request.headers, + 'Authorization', + 'Basic Zm9vOmJhcg==')) + def tearDown(self): """ This method is called after each test. Currently it does nothing. diff --git a/src/lib/http/Makefile.am b/src/lib/http/Makefile.am index 78a7799902..18b1b5db4d 100644 --- a/src/lib/http/Makefile.am +++ b/src/lib/http/Makefile.am @@ -38,6 +38,7 @@ libkea_http_la_SOURCES += response_creator.cc response_creator.h libkea_http_la_SOURCES += response_creator_factory.h libkea_http_la_SOURCES += response_json.cc response_json.h libkea_http_la_SOURCES += url.cc url.h +libkea_http_la_SOURCES += basic_auth.cc basic_auth.h libkea_http_la_CXXFLAGS = $(AM_CXXFLAGS) libkea_http_la_CPPFLAGS = $(AM_CPPFLAGS) diff --git a/src/lib/http/basic_auth.cc b/src/lib/http/basic_auth.cc new file mode 100644 index 0000000000..fa8a80843f --- /dev/null +++ b/src/lib/http/basic_auth.cc @@ -0,0 +1,49 @@ +// Copyright (C) 2020 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include + +#include +#include +#include + +using namespace isc::util::encode; +using namespace std; + +namespace isc { +namespace http { + +BasicHttpAuth::BasicHttpAuth(const std::string& user, + const std::string& password) + : user_(user), password_(password) { + if (user.find(':') != string::npos) { + isc_throw(BadValue, "user '" << user << "' must not contain a ':'"); + } + buildSecret(); + buildCredential(); +} + +BasicHttpAuth::BasicHttpAuth(const std::string& secret) : secret_(secret) { + if (secret.find(':') == string::npos) { + isc_throw(BadValue, "secret '" << secret << "' must contain a ':"); + } + buildCredential(); +} + +void BasicHttpAuth::buildSecret() { + secret_ = user_ + ":" + password_; +} + +void BasicHttpAuth::buildCredential() { + credential_ = encodeBase64(encodeUtf8(secret_)); +} + +bool allow(const std::string& credential, const BasicHttpAuthList& list) { + return (list.count(credential) != 0); +} + +} // end of namespace isc::http +} // end of namespace isc diff --git a/src/lib/http/basic_auth.h b/src/lib/http/basic_auth.h new file mode 100644 index 0000000000..d72dcc0a64 --- /dev/null +++ b/src/lib/http/basic_auth.h @@ -0,0 +1,84 @@ +// Copyright (C) 2020 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef BASIC_HTTP_AUTH_H +#define BASIC_HTTP_AUTH_H + +#include +#include +#include +#include + +namespace isc { +namespace http { + +/// @brief Represents a basic HTTP authentication. +/// +/// It computes the credential from user and password. +class BasicHttpAuth { +public: + + /// @brief Constructor. + /// + /// @param user User name + /// @param password Password + /// @throw BadValue if user contains the ':' character. + BasicHttpAuth(const std::string& user, const std::string& password); + + /// @brief Constructor. + /// + /// @param secret user:password string + /// @throw BadValue if secret does not contain the ';' character. + BasicHttpAuth(const std::string& secret); + + /// @brief Returns the secret. + const std::string& getSecret() const { + return (secret_); + } + + /// @brief Returns the credential (base64 of the UTF-8 secret). + const std::string& getCredential() const { + return (credential_); + } + +private: + + /// @brief Build the secret from user and password. + void buildSecret(); + + /// @brief Build the credential from the secret. + void buildCredential(); + + /// @brief User name. + std::string user_; + + /// @brief Password. + std::string password_; + + /// @brief Secret. + std::string secret_; + + /// @brief Credential. + std::string credential_; +}; + +/// @brief Type of pointers to basic HTTP authentication objects. +typedef boost::shared_ptr BasicHttpAuthPtr; + +/// @brief Type of basic HTTP authentication credential list. +typedef std::unordered_set BasicHttpAuthList; + +/// @brief Verify if a credential is authorized. +/// +/// @param credential Credential to validate. +/// @param list List of authorized credentials. +/// @return True if authorized, false otherwise. +bool allow(const std::string& credential, const BasicHttpAuthList& list); + +} // end of namespace isc::http +} // end of namespace isc + +#endif // endif BASIC_HTTP_AUTH_H diff --git a/src/lib/http/tests/Makefile.am b/src/lib/http/tests/Makefile.am index fc9c8b427d..9ee3bd9bb6 100644 --- a/src/lib/http/tests/Makefile.am +++ b/src/lib/http/tests/Makefile.am @@ -20,7 +20,8 @@ TESTS = if HAVE_GTEST TESTS += libhttp_unittests -libhttp_unittests_SOURCES = connection_pool_unittests.cc +libhttp_unittests_SOURCES = basic_auth_unittests.cc +libhttp_unittests_SOURCES += connection_pool_unittests.cc libhttp_unittests_SOURCES += date_time_unittests.cc libhttp_unittests_SOURCES += http_header_unittests.cc libhttp_unittests_SOURCES += post_request_unittests.cc diff --git a/src/lib/http/tests/basic_auth_unittests.cc b/src/lib/http/tests/basic_auth_unittests.cc new file mode 100644 index 0000000000..cb679e0515 --- /dev/null +++ b/src/lib/http/tests/basic_auth_unittests.cc @@ -0,0 +1,55 @@ +// Copyright (C) 2020 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include +#include +#include + +using namespace isc; +using namespace isc::http; + +namespace { + +// Test that user name with a colon is rejected. +TEST(BasicHttpAuthTest, userColon) { + BasicHttpAuthPtr ba; + EXPECT_THROW(ba.reset(new BasicHttpAuth("foo:bar", "")), BadValue); +} + +// Test that secret without a colon is rejected. +TEST(BasicHttpAuthTest, secretNoColon) { + BasicHttpAuthPtr ba; + EXPECT_THROW(ba.reset(new BasicHttpAuth("foo-bar")), BadValue); +} + +// Test that valid user and password work. +TEST(BasicHttpAuthTest, user) { + BasicHttpAuthPtr ba; + EXPECT_NO_THROW(ba.reset(new BasicHttpAuth("foo", "bar"))); + ASSERT_TRUE(ba); + EXPECT_EQ("foo:bar", ba->getSecret()); + EXPECT_EQ("Zm9vOmJhcg==", ba->getCredential()); +} + +// Test that valid secret work. +TEST(BasicHttpAuthTest, secret) { + BasicHttpAuthPtr ba; + EXPECT_NO_THROW(ba.reset(new BasicHttpAuth("foo:bar"))); + ASSERT_TRUE(ba); + EXPECT_EQ("foo:bar", ba->getSecret()); + EXPECT_EQ("Zm9vOmJhcg==", ba->getCredential()); +} + +// Test that secret is encoded in UTF-8. +TEST(BasicHttpAuthTest, utf8) { + BasicHttpAuthPtr ba; + EXPECT_NO_THROW(ba.reset(new BasicHttpAuth("foo\n", "b\ar"))); + ASSERT_TRUE(ba); + EXPECT_EQ("foo\n:b\ar", ba->getSecret()); + EXPECT_EQ("Zm9vCjpiB3I=", ba->getCredential()); +} + +} // end of anonymous namespace -- GitLab From 74d89a019e54db3885b13b44851912c4e030b36e Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Sat, 11 Jul 2020 18:42:06 +0200 Subject: [PATCH 03/33] [#1304] Fixed unicode handling --- src/bin/shell/kea-shell.in | 13 ++++++++----- src/bin/shell/tests/shell_unittest.py.in | 24 ++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/bin/shell/kea-shell.in b/src/bin/shell/kea-shell.in index d4fa02f101..32125655c2 100644 --- a/src/bin/shell/kea-shell.in +++ b/src/bin/shell/kea-shell.in @@ -30,9 +30,12 @@ from kea_conn import CARequest # CAResponse if sys.version_info[0] == 2: # This is Python 2.x import kea_connector2 as kea_connector + def auth8(s): + return unicode(s, 'utf-8') elif sys.version_info[0] == 3: # This is Python 3.x import kea_connector3 as kea_connector + auth8 = str else: # This is... have no idea what it is. raise SystemExit("Unknown python version:" + str(sys.version_info[0])) @@ -70,9 +73,9 @@ def shell_body(): parser.add_argument('--service', nargs="?", action="append", help='target spcified service. If not specified,' 'control agent will receive command.') - parser.add_argument('--auth-user', type=str, default='', + parser.add_argument('--auth-user', type=auth8, default='', help='Basic HTTP authentication user') - parser.add_argument('--auth-password', type=str, default='', + parser.add_argument('--auth-password', type=auth8, default='', help='Basic HTTP authentication password') parser.add_argument('command', type=str, nargs="?", default='list-commands', @@ -94,9 +97,9 @@ def shell_body(): params.http_port = cmd_args.port params.path += cmd_args.path if cmd_args.auth_user is not '': - user = cmd_args.auth_user.encode('latin1') - password = cmd_args.auth_password.encode('latin1') - secret = b':'.join((user, password)) + user = cmd_args.auth_user + password = cmd_args.auth_password + secret = b':'.join((user.encode('utf-8'), password.encode('utf-8'))) if sys.version_info[0] == 3: params.auth = b64encode(secret).strip().decode('ascii') else: diff --git a/src/bin/shell/tests/shell_unittest.py.in b/src/bin/shell/tests/shell_unittest.py.in index 74c320749f..b65b65c727 100644 --- a/src/bin/shell/tests/shell_unittest.py.in +++ b/src/bin/shell/tests/shell_unittest.py.in @@ -147,8 +147,8 @@ class CARequestUnitTest(unittest.TestCase): """ user = 'foo' password = 'bar' - buser = user.encode('latin1') - bpassword = password.encode('latin1') + buser = user.encode('utf-8') + bpassword = password.encode('utf-8') secret = b':'.join((buser, bpassword)) self.assertEqual(b'foo:bar', secret) if sys.version_info[0] == 3: @@ -157,6 +157,26 @@ class CARequestUnitTest(unittest.TestCase): auth = b64encode(secret).strip().encode('ascii') self.assertEqual('Zm9vOmJhcg==', auth) + def test_auth_unicode(self): + """ + This test check if the basic HTTP authentication uses UTF-8 encoding. + """ + if sys.version_info[0] == 3: + user = 'libert\xe9' + password = '\xe9galit\xe9' + else: + user = u'libert\xe9' + password = u'\xe9galit\xe9' + buser = user.encode('utf-8') + bpassword = password.encode('utf-8') + secret = b':'.join((buser, bpassword)) + self.assertEqual(b'libert\xc3\xa9:\xc3\xa9galit\xc3\xa9', secret) + if sys.version_info[0] == 3: + auth = b64encode(secret).strip().decode('ascii') + else: + auth = b64encode(secret).strip().encode('ascii') + self.assertEqual('bGliZXJ0w6k6w6lnYWxpdMOp', auth) + def test_header_auth(self): """ This test checks if the basic HTTP authentication header is -- GitLab From cb88a01789dfdd46ed280e8b074137ab3980f0b0 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Sat, 11 Jul 2020 19:18:40 +0200 Subject: [PATCH 04/33] [#1304] Cosmetics --- src/bin/shell/kea-shell.in | 10 +++---- src/bin/shell/tests/shell_process_tests.sh.in | 4 +-- src/bin/shell/tests/shell_unittest.py.in | 29 +++++++++---------- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src/bin/shell/kea-shell.in b/src/bin/shell/kea-shell.in index 32125655c2..f229040857 100644 --- a/src/bin/shell/kea-shell.in +++ b/src/bin/shell/kea-shell.in @@ -17,7 +17,6 @@ Text client for Control Agent process # that's a stand alone package that requires separate installation. One of # the design requirements was to not require any additional packages, so # the code uses standard libraries available in python. Hence two versions. -import os import sys import signal import argparse @@ -30,8 +29,9 @@ from kea_conn import CARequest # CAResponse if sys.version_info[0] == 2: # This is Python 2.x import kea_connector2 as kea_connector - def auth8(s): - return unicode(s, 'utf-8') + def auth8(string): + """Convert str into unicode""" + return unicode(string, 'utf-8') elif sys.version_info[0] == 3: # This is Python 3.x import kea_connector3 as kea_connector @@ -86,7 +86,7 @@ def shell_body(): if cmd_args.v: print(VERSION) - exit(0) + sys.exit(0) # Ok, now it's time to put the parameters parsed into the structure to be # used by the connection. @@ -96,7 +96,7 @@ def shell_body(): params.http_host = cmd_args.host params.http_port = cmd_args.port params.path += cmd_args.path - if cmd_args.auth_user is not '': + if cmd_args.auth_user != '': user = cmd_args.auth_user password = cmd_args.auth_password secret = b':'.join((user.encode('utf-8'), password.encode('utf-8'))) diff --git a/src/bin/shell/tests/shell_process_tests.sh.in b/src/bin/shell/tests/shell_process_tests.sh.in index a176ac0013..9b94868155 100644 --- a/src/bin/shell/tests/shell_process_tests.sh.in +++ b/src/bin/shell/tests/shell_process_tests.sh.in @@ -58,7 +58,7 @@ shell_command_test() { # Log the start of the test and print test name. test_start ${test_name} - + # Remove any dangling CA instances and remove log files. cleanup @@ -100,7 +100,7 @@ shell_command_test() { tmp="echo \"${params}\" | ${shell_bin_path}/${shell_bin} --host \ 127.0.0.1 --port 8081 ${cmd} > ${tmpfile_path}/shell-stdout.txt" echo "Executing kea-shell ($tmp)" - + echo "${params}" | ${shell_bin_path}/${shell_bin} --host 127.0.0.1 \ --port 8081 ${cmd} > ${tmpfile_path}/shell-stdout.txt diff --git a/src/bin/shell/tests/shell_unittest.py.in b/src/bin/shell/tests/shell_unittest.py.in index b65b65c727..08a05f53dc 100644 --- a/src/bin/shell/tests/shell_unittest.py.in +++ b/src/bin/shell/tests/shell_unittest.py.in @@ -26,7 +26,6 @@ class CARequestUnitTest(unittest.TestCase): """ This method is called before each test. Currently it does nothing. """ - pass def test_body_with_service(self): """ @@ -35,9 +34,10 @@ class CARequestUnitTest(unittest.TestCase): """ request = CARequest() request.command = "foo" - request.service= ["service1"] + request.service = ["service1"] request.generate_body() - self.assertEqual(request.content, '{ "command": "foo", "service": ["service1"] }') + self.assertEqual(request.content, + '{ "command": "foo", "service": ["service1"] }') def test_body_with_multiple_service(self): """ @@ -46,9 +46,10 @@ class CARequestUnitTest(unittest.TestCase): """ request = CARequest() request.command = "foo" - request.service= ["service1","service2/2"] + request.service = ["service1", "service2/2"] request.generate_body() - self.assertEqual(request.content, '{ "command": "foo", "service": ["service1","service2/2"] }') + self.assertEqual(request.content, + '{ "command": "foo", "service": ["service1","service2/2"] }') def test_body_with_malformed_service(self): """ @@ -57,9 +58,10 @@ class CARequestUnitTest(unittest.TestCase): """ request = CARequest() request.command = "foo" - request.service= ["service1",""] + request.service = ["service1", ""] request.generate_body() - self.assertEqual(request.content, '{ "command": "foo", "service": ["service1"] }') + self.assertEqual(request.content, + '{ "command": "foo", "service": ["service1"] }') def test_body_without_args(self): """ @@ -92,14 +94,12 @@ class CARequestUnitTest(unittest.TestCase): if header_name in headers: if headers[header_name] == value: return True - else: - print("Expected value: " + value + - " does not match actual value: " + - headers[header_name]) - return False - else: - print("Expected header: " + header_name + " missing") + print("Expected value: " + value + + " does not match actual value: " + + headers[header_name]) return False + print("Expected header: " + header_name + " missing") + return False def test_headers(self): """ @@ -194,7 +194,6 @@ class CARequestUnitTest(unittest.TestCase): """ This method is called after each test. Currently it does nothing. """ - pass if __name__ == '__main__': unittest.main() -- GitLab From 9788e4796f97f468e5836647b02f3527d121e5c9 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Sat, 11 Jul 2020 21:50:06 +0200 Subject: [PATCH 05/33] [#1304] Updated http client --- src/lib/http/post_request.cc | 7 ++-- src/lib/http/post_request.h | 8 +++-- src/lib/http/post_request_json.cc | 7 ++-- src/lib/http/post_request_json.h | 7 ++-- src/lib/http/request.cc | 10 ++++-- src/lib/http/request.h | 8 +++-- src/lib/http/tests/basic_auth_unittests.cc | 38 +++++++++++----------- src/lib/http/tests/request_unittests.cc | 33 ++++++++++++++++++- 8 files changed, 83 insertions(+), 35 deletions(-) diff --git a/src/lib/http/post_request.cc b/src/lib/http/post_request.cc index f7a8090fe9..1658985af7 100644 --- a/src/lib/http/post_request.cc +++ b/src/lib/http/post_request.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2016-2019 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2016-2020 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -20,8 +20,9 @@ PostHttpRequest::PostHttpRequest() PostHttpRequest::PostHttpRequest(const Method& method, const std::string& uri, const HttpVersion& version, - const HostHttpHeader& host_header) - : HttpRequest(method, uri, version, host_header) { + const HostHttpHeader& host_header, + const BasicHttpAuthPtr& basic_auth) + : HttpRequest(method, uri, version, host_header, basic_auth) { requireHttpMethod(Method::HTTP_POST); requireHeader("Content-Length"); requireHeader("Content-Type"); diff --git a/src/lib/http/post_request.h b/src/lib/http/post_request.h index 1426087944..095fdab7c9 100644 --- a/src/lib/http/post_request.h +++ b/src/lib/http/post_request.h @@ -1,4 +1,4 @@ -// Copyright (C) 2016-2019 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2016-2020 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -39,9 +39,11 @@ public: /// @param version HTTP version. /// @param host_header Host header to be included in the request. The default /// is the empty Host header. + /// @param basic_auth Basic HTTP authentication credential. The default + /// is no authentication. PostHttpRequest(const Method& method, const std::string& uri, const HttpVersion& version, - const HostHttpHeader& host_header = HostHttpHeader()); - + const HostHttpHeader& host_header = HostHttpHeader(), + const BasicHttpAuthPtr& basic_auth = BasicHttpAuthPtr()); }; diff --git a/src/lib/http/post_request_json.cc b/src/lib/http/post_request_json.cc index 887af204e9..d3e9b96545 100644 --- a/src/lib/http/post_request_json.cc +++ b/src/lib/http/post_request_json.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2016-2019 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2016-2020 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -20,8 +20,9 @@ PostHttpRequestJson::PostHttpRequestJson() PostHttpRequestJson::PostHttpRequestJson(const Method& method, const std::string& uri, const HttpVersion& version, - const HostHttpHeader& host_header) - : PostHttpRequest(method, uri, version, host_header) { + const HostHttpHeader& host_header, + const BasicHttpAuthPtr& basic_auth) + : PostHttpRequest(method, uri, version, host_header, basic_auth) { requireHeaderValue("Content-Type", "application/json"); context()->headers_.push_back(HttpHeaderContext("Content-Type", "application/json")); } diff --git a/src/lib/http/post_request_json.h b/src/lib/http/post_request_json.h index f4f37b3edd..6d7f82a8af 100644 --- a/src/lib/http/post_request_json.h +++ b/src/lib/http/post_request_json.h @@ -1,4 +1,4 @@ -// Copyright (C) 2016-2019 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2016-2020 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -52,9 +52,12 @@ public: /// @param version HTTP version. /// @param host_header Host header to be included in the request. The default /// is the empty Host header. + /// @param basic_auth Basic HTTP authentication credential. The default + /// is no authentication. explicit PostHttpRequestJson(const Method& method, const std::string& uri, const HttpVersion& version, - const HostHttpHeader& host_header = HostHttpHeader()); + const HostHttpHeader& host_header = HostHttpHeader(), + const BasicHttpAuthPtr& basic_auth = BasicHttpAuthPtr()); /// @brief Complete parsing of the HTTP request. /// diff --git a/src/lib/http/request.cc b/src/lib/http/request.cc index 4bc8d31fa9..21926034b1 100644 --- a/src/lib/http/request.cc +++ b/src/lib/http/request.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2016-2019 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2016-2020 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -30,7 +30,8 @@ HttpRequest::HttpRequest() HttpRequest::HttpRequest(const Method& method, const std::string& uri, const HttpVersion& version, - const HostHttpHeader& host_header) + const HostHttpHeader& host_header, + const BasicHttpAuthPtr& basic_auth) : HttpMessage(OUTBOUND), required_methods_(), method_(Method::HTTP_METHOD_UNKNOWN), context_(new HttpRequestContext()) { @@ -43,6 +44,11 @@ HttpRequest::HttpRequest(const Method& method, // harm to include it. context()->headers_.push_back(HttpHeaderContext(host_header.getName(), host_header.getValue())); + if (basic_auth) { + context()->headers_.push_back(HttpHeaderContext("Authorization", + "Basic " + + basic_auth->getCredential())); + } } void diff --git a/src/lib/http/request.h b/src/lib/http/request.h index dc06600a53..1b26b1c48f 100644 --- a/src/lib/http/request.h +++ b/src/lib/http/request.h @@ -1,4 +1,4 @@ -// Copyright (C) 2016-2019 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2016-2020 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -7,6 +7,7 @@ #ifndef HTTP_REQUEST_H #define HTTP_REQUEST_H +#include #include #include #include @@ -73,8 +74,11 @@ public: /// @param version HTTP version. /// @param host_header Host header to be included in the request. The default /// is the empty Host header. + /// @param basic_auth Basic HTTP authentication credential. The default + /// is no authentication. HttpRequest(const Method& method, const std::string& uri, const HttpVersion& version, - const HostHttpHeader& host_header = HostHttpHeader()); + const HostHttpHeader& host_header = HostHttpHeader(), + const BasicHttpAuthPtr& basic_auth = BasicHttpAuthPtr()); /// @brief Returns pointer to the @ref HttpRequestContext. /// diff --git a/src/lib/http/tests/basic_auth_unittests.cc b/src/lib/http/tests/basic_auth_unittests.cc index cb679e0515..305e57fef7 100644 --- a/src/lib/http/tests/basic_auth_unittests.cc +++ b/src/lib/http/tests/basic_auth_unittests.cc @@ -15,41 +15,41 @@ namespace { // Test that user name with a colon is rejected. TEST(BasicHttpAuthTest, userColon) { - BasicHttpAuthPtr ba; - EXPECT_THROW(ba.reset(new BasicHttpAuth("foo:bar", "")), BadValue); + BasicHttpAuthPtr basic_auth; + EXPECT_THROW(basic_auth.reset(new BasicHttpAuth("foo:bar", "")), BadValue); } // Test that secret without a colon is rejected. TEST(BasicHttpAuthTest, secretNoColon) { - BasicHttpAuthPtr ba; - EXPECT_THROW(ba.reset(new BasicHttpAuth("foo-bar")), BadValue); + BasicHttpAuthPtr basic_auth; + EXPECT_THROW(basic_auth.reset(new BasicHttpAuth("foo-bar")), BadValue); } // Test that valid user and password work. TEST(BasicHttpAuthTest, user) { - BasicHttpAuthPtr ba; - EXPECT_NO_THROW(ba.reset(new BasicHttpAuth("foo", "bar"))); - ASSERT_TRUE(ba); - EXPECT_EQ("foo:bar", ba->getSecret()); - EXPECT_EQ("Zm9vOmJhcg==", ba->getCredential()); + BasicHttpAuthPtr basic_auth; + EXPECT_NO_THROW(basic_auth.reset(new BasicHttpAuth("foo", "bar"))); + ASSERT_TRUE(basic_auth); + EXPECT_EQ("foo:bar", basic_auth->getSecret()); + EXPECT_EQ("Zm9vOmJhcg==", basic_auth->getCredential()); } // Test that valid secret work. TEST(BasicHttpAuthTest, secret) { - BasicHttpAuthPtr ba; - EXPECT_NO_THROW(ba.reset(new BasicHttpAuth("foo:bar"))); - ASSERT_TRUE(ba); - EXPECT_EQ("foo:bar", ba->getSecret()); - EXPECT_EQ("Zm9vOmJhcg==", ba->getCredential()); + BasicHttpAuthPtr basic_auth; + EXPECT_NO_THROW(basic_auth.reset(new BasicHttpAuth("foo:bar"))); + ASSERT_TRUE(basic_auth); + EXPECT_EQ("foo:bar", basic_auth->getSecret()); + EXPECT_EQ("Zm9vOmJhcg==", basic_auth->getCredential()); } // Test that secret is encoded in UTF-8. TEST(BasicHttpAuthTest, utf8) { - BasicHttpAuthPtr ba; - EXPECT_NO_THROW(ba.reset(new BasicHttpAuth("foo\n", "b\ar"))); - ASSERT_TRUE(ba); - EXPECT_EQ("foo\n:b\ar", ba->getSecret()); - EXPECT_EQ("Zm9vCjpiB3I=", ba->getCredential()); + BasicHttpAuthPtr basic_auth; + EXPECT_NO_THROW(basic_auth.reset(new BasicHttpAuth("foo\n", "b\ar"))); + ASSERT_TRUE(basic_auth); + EXPECT_EQ("foo\n:b\ar", basic_auth->getSecret()); + EXPECT_EQ("Zm9vCjpiB3I=", basic_auth->getCredential()); } } // end of anonymous namespace diff --git a/src/lib/http/tests/request_unittests.cc b/src/lib/http/tests/request_unittests.cc index 65febe7990..0bc25b322b 100644 --- a/src/lib/http/tests/request_unittests.cc +++ b/src/lib/http/tests/request_unittests.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2016-2019 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2016-2020 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -358,4 +358,35 @@ TEST_F(HttpRequestTest, toBriefString) { EXPECT_EQ("POST /isc/org HTTP/1.1", request_->toBriefString()); } +// This test verifies that no basic HTTP authentication is supported. +TEST_F(HttpRequestTest, noBasicAuth) { + ASSERT_NO_THROW(request_.reset(new HttpRequest(HttpRequest::Method::HTTP_GET, + "/isc/org", + HttpVersion(1, 1), + HostHttpHeader("www.example.org")))); + + ASSERT_NO_THROW(request_->finalize()); + ASSERT_THROW(request_->getHeader("Authorization"), + HttpMessageNonExistingHeader); +} + +// This test verifies that basic HTTP authentication works as expected. +TEST_F(HttpRequestTest, basicAuth) { + BasicHttpAuthPtr basic_auth; + EXPECT_NO_THROW(basic_auth.reset(new BasicHttpAuth("foo", "bar"))); + ASSERT_TRUE(basic_auth); + + ASSERT_NO_THROW(request_.reset(new HttpRequest(HttpRequest::Method::HTTP_GET, + "/isc/org", + HttpVersion(1, 1), + HostHttpHeader("www.example.org"), + basic_auth))); + + ASSERT_NO_THROW(request_->finalize()); + + std::string value; + EXPECT_NO_THROW(value = request_->getHeaderValue("Authorization")); + EXPECT_EQ(value, "Basic " + basic_auth->getCredential()); +} + } -- GitLab From b731c1fc03d1053ac16777a84800664e10db7b01 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Sun, 12 Jul 2020 09:38:09 +0200 Subject: [PATCH 06/33] [#1304] Updated http response creator --- src/lib/http/Makefile.am | 1 + src/lib/http/basic_auth.cc | 4 - src/lib/http/basic_auth.h | 24 +-- src/lib/http/http_messages.cc | 10 +- src/lib/http/http_messages.h | 6 +- src/lib/http/http_messages.mes | 18 +- src/lib/http/request.cc | 4 +- src/lib/http/response_creator_auth.cc | 66 +++++++ src/lib/http/response_creator_auth.h | 35 ++++ src/lib/http/tests/Makefile.am | 3 +- src/lib/http/tests/basic_auth_unittests.cc | 10 + .../http/tests/response_creator_unittests.cc | 180 +++++++++++++++++- 12 files changed, 338 insertions(+), 23 deletions(-) create mode 100644 src/lib/http/response_creator_auth.cc create mode 100644 src/lib/http/response_creator_auth.h diff --git a/src/lib/http/Makefile.am b/src/lib/http/Makefile.am index 18b1b5db4d..64c07b7775 100644 --- a/src/lib/http/Makefile.am +++ b/src/lib/http/Makefile.am @@ -35,6 +35,7 @@ libkea_http_la_SOURCES += response.cc response.h libkea_http_la_SOURCES += response_parser.cc response_parser.h libkea_http_la_SOURCES += response_context.h libkea_http_la_SOURCES += response_creator.cc response_creator.h +libkea_http_la_SOURCES += response_creator_auth.cc response_creator_auth.h libkea_http_la_SOURCES += response_creator_factory.h libkea_http_la_SOURCES += response_json.cc response_json.h libkea_http_la_SOURCES += url.cc url.h diff --git a/src/lib/http/basic_auth.cc b/src/lib/http/basic_auth.cc index fa8a80843f..f3a1d871ef 100644 --- a/src/lib/http/basic_auth.cc +++ b/src/lib/http/basic_auth.cc @@ -41,9 +41,5 @@ void BasicHttpAuth::buildCredential() { credential_ = encodeBase64(encodeUtf8(secret_)); } -bool allow(const std::string& credential, const BasicHttpAuthList& list) { - return (list.count(credential) != 0); -} - } // end of namespace isc::http } // end of namespace isc diff --git a/src/lib/http/basic_auth.h b/src/lib/http/basic_auth.h index d72dcc0a64..3968e56de1 100644 --- a/src/lib/http/basic_auth.h +++ b/src/lib/http/basic_auth.h @@ -7,9 +7,9 @@ #ifndef BASIC_HTTP_AUTH_H #define BASIC_HTTP_AUTH_H +#include #include #include -#include #include namespace isc { @@ -23,7 +23,7 @@ public: /// @brief Constructor. /// - /// @param user User name + /// @param user User id /// @param password Password /// @throw BadValue if user contains the ':' character. BasicHttpAuth(const std::string& user, const std::string& password); @@ -52,7 +52,7 @@ private: /// @brief Build the credential from the secret. void buildCredential(); - /// @brief User name. + /// @brief User id. std::string user_; /// @brief Password. @@ -68,15 +68,17 @@ private: /// @brief Type of pointers to basic HTTP authentication objects. typedef boost::shared_ptr BasicHttpAuthPtr; -/// @brief Type of basic HTTP authentication credential list. -typedef std::unordered_set BasicHttpAuthList; +/// @brief Represents basic HTTP authentication header. +struct BasicAuthHttpHeaderContext : public HttpHeaderContext { -/// @brief Verify if a credential is authorized. -/// -/// @param credential Credential to validate. -/// @param list List of authorized credentials. -/// @return True if authorized, false otherwise. -bool allow(const std::string& credential, const BasicHttpAuthList& list); + /// @brief Constructor. + /// + /// @param basic_auth Basic HTTP authentication object. + explicit BasicAuthHttpHeaderContext(const BasicHttpAuth& basic_auth) + : HttpHeaderContext("Authorization", + "Basic " + basic_auth.getCredential()) { + } +}; } // end of namespace isc::http } // end of namespace isc diff --git a/src/lib/http/http_messages.cc b/src/lib/http/http_messages.cc index 52216ca2af..73068a1a80 100644 --- a/src/lib/http/http_messages.cc +++ b/src/lib/http/http_messages.cc @@ -1,4 +1,4 @@ -// File created from ../../../src/lib/http/http_messages.mes on Mon Jun 22 2020 17:27 +// File created from ../../../src/lib/http/http_messages.mes on Sun Jul 12 2020 02:08 #include #include @@ -11,6 +11,10 @@ extern const isc::log::MessageID HTTP_BAD_CLIENT_REQUEST_RECEIVED = "HTTP_BAD_CL extern const isc::log::MessageID HTTP_BAD_CLIENT_REQUEST_RECEIVED_DETAILS = "HTTP_BAD_CLIENT_REQUEST_RECEIVED_DETAILS"; extern const isc::log::MessageID HTTP_BAD_SERVER_RESPONSE_RECEIVED = "HTTP_BAD_SERVER_RESPONSE_RECEIVED"; extern const isc::log::MessageID HTTP_BAD_SERVER_RESPONSE_RECEIVED_DETAILS = "HTTP_BAD_SERVER_RESPONSE_RECEIVED_DETAILS"; +extern const isc::log::MessageID HTTP_CLIENT_REQUEST_AUTHORIZED = "HTTP_CLIENT_REQUEST_AUTHORIZED"; +extern const isc::log::MessageID HTTP_CLIENT_REQUEST_BAD_AUTH_HEADER = "HTTP_CLIENT_REQUEST_BAD_AUTH_HEADER"; +extern const isc::log::MessageID HTTP_CLIENT_REQUEST_NOT_AUTHORIZED = "HTTP_CLIENT_REQUEST_NOT_AUTHORIZED"; +extern const isc::log::MessageID HTTP_CLIENT_REQUEST_NO_AUTH_HEADER = "HTTP_CLIENT_REQUEST_NO_AUTH_HEADER"; extern const isc::log::MessageID HTTP_CLIENT_REQUEST_RECEIVED = "HTTP_CLIENT_REQUEST_RECEIVED"; extern const isc::log::MessageID HTTP_CLIENT_REQUEST_RECEIVED_DETAILS = "HTTP_CLIENT_REQUEST_RECEIVED_DETAILS"; extern const isc::log::MessageID HTTP_CLIENT_REQUEST_SEND = "HTTP_CLIENT_REQUEST_SEND"; @@ -38,6 +42,10 @@ const char* values[] = { "HTTP_BAD_CLIENT_REQUEST_RECEIVED_DETAILS", "detailed information about bad request received from %1:\n%2", "HTTP_BAD_SERVER_RESPONSE_RECEIVED", "bad response received when communicating with %1: %2", "HTTP_BAD_SERVER_RESPONSE_RECEIVED_DETAILS", "detailed information about bad response received from %1:\n%2", + "HTTP_CLIENT_REQUEST_AUTHORIZED", "received HTTP request authorized for '%1'", + "HTTP_CLIENT_REQUEST_BAD_AUTH_HEADER", "received HTTP request with malformed authentication header: %1", + "HTTP_CLIENT_REQUEST_NOT_AUTHORIZED", "received HTTP request with not matching authentication header", + "HTTP_CLIENT_REQUEST_NO_AUTH_HEADER", "received HTTP request without required authentication header", "HTTP_CLIENT_REQUEST_RECEIVED", "received HTTP request from %1", "HTTP_CLIENT_REQUEST_RECEIVED_DETAILS", "detailed information about well formed request received from %1:\n%2", "HTTP_CLIENT_REQUEST_SEND", "sending HTTP request %1 to %2", diff --git a/src/lib/http/http_messages.h b/src/lib/http/http_messages.h index 7980531d88..91d5392dfd 100644 --- a/src/lib/http/http_messages.h +++ b/src/lib/http/http_messages.h @@ -1,4 +1,4 @@ -// File created from ../../../src/lib/http/http_messages.mes on Mon Jun 22 2020 17:27 +// File created from ../../../src/lib/http/http_messages.mes on Sun Jul 12 2020 02:08 #ifndef HTTP_MESSAGES_H #define HTTP_MESSAGES_H @@ -12,6 +12,10 @@ extern const isc::log::MessageID HTTP_BAD_CLIENT_REQUEST_RECEIVED; extern const isc::log::MessageID HTTP_BAD_CLIENT_REQUEST_RECEIVED_DETAILS; extern const isc::log::MessageID HTTP_BAD_SERVER_RESPONSE_RECEIVED; extern const isc::log::MessageID HTTP_BAD_SERVER_RESPONSE_RECEIVED_DETAILS; +extern const isc::log::MessageID HTTP_CLIENT_REQUEST_AUTHORIZED; +extern const isc::log::MessageID HTTP_CLIENT_REQUEST_BAD_AUTH_HEADER; +extern const isc::log::MessageID HTTP_CLIENT_REQUEST_NOT_AUTHORIZED; +extern const isc::log::MessageID HTTP_CLIENT_REQUEST_NO_AUTH_HEADER; extern const isc::log::MessageID HTTP_CLIENT_REQUEST_RECEIVED; extern const isc::log::MessageID HTTP_CLIENT_REQUEST_RECEIVED_DETAILS; extern const isc::log::MessageID HTTP_CLIENT_REQUEST_SEND; diff --git a/src/lib/http/http_messages.mes b/src/lib/http/http_messages.mes index a6325e010a..cbd173fb5c 100644 --- a/src/lib/http/http_messages.mes +++ b/src/lib/http/http_messages.mes @@ -1,4 +1,4 @@ -# Copyright (C) 2016-2019 Internet Systems Consortium, Inc. ("ISC") +# Copyright (C) 2016-2020 Internet Systems Consortium, Inc. ("ISC") # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this @@ -33,6 +33,22 @@ from the server. The first argument specifies an URL of the server. The second argument provides a response in the textual format. The request is truncated by the logger if it is too large to be printed. +% HTTP_CLIENT_REQUEST_AUTHORIZED received HTTP request authorized for '%1' +This debug message is issued when the server receives with a matching +authentication header. The argument provides the user name. + +% HTTP_CLIENT_REQUEST_BAD_AUTH_HEADER received HTTP request with malformed authentication header: %1 +This information message is issued when the server receives a request with +a malformed authentication header. The argument explains the problem. + +% HTTP_CLIENT_REQUEST_NOT_AUTHORIZED received HTTP request with not matching authentication header +This information message is issued when the server receives a request with +authentication header carrying not recognized credential. + +% HTTP_CLIENT_REQUEST_NO_AUTH_HEADER received HTTP request without required authentication header +This information message is issued when the server receives a request without +a required authentication header. + % HTTP_CLIENT_REQUEST_RECEIVED received HTTP request from %1 This debug message is issued when the server finished receiving a HTTP request from the remote endpoint. The address of the remote endpoint is diff --git a/src/lib/http/request.cc b/src/lib/http/request.cc index 21926034b1..15f7b614e6 100644 --- a/src/lib/http/request.cc +++ b/src/lib/http/request.cc @@ -45,9 +45,7 @@ HttpRequest::HttpRequest(const Method& method, context()->headers_.push_back(HttpHeaderContext(host_header.getName(), host_header.getValue())); if (basic_auth) { - context()->headers_.push_back(HttpHeaderContext("Authorization", - "Basic " + - basic_auth->getCredential())); + context()->headers_.push_back(BasicAuthHttpHeaderContext(*basic_auth)); } } diff --git a/src/lib/http/response_creator_auth.cc b/src/lib/http/response_creator_auth.cc new file mode 100644 index 0000000000..21c13ee028 --- /dev/null +++ b/src/lib/http/response_creator_auth.cc @@ -0,0 +1,66 @@ +// Copyright (C) 2020 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include + +#include +#include +#include + +using namespace isc; +using namespace isc::util; +using namespace std; + +namespace isc { +namespace http { + +HttpResponsePtr checkBasicHttpAuth(HttpResponseCreatorPtr creator, + const ConstHttpRequestPtr& request, + const BasicHttpAuthMap& credentials, + const std::string& realm) { + try { + string value = request->getHeaderValue("Authorization"); + // Trim space characters. + value = str::trim(value); + if (value.size() < 8) { + isc_throw(BadValue, "header content is too short"); + } + // Get the authentication scheme which must be "basic". + string scheme = value.substr(0, 5); + str::lowercase(scheme); + if (scheme != "basic") { + isc_throw(BadValue, "not basic authentication"); + } + // Skip the authentication scheme name and space characters. + value = value.substr(5); + value = str::trim(value); + // Verify the credential is in the list. + const auto it = credentials.find(value); + if (it != credentials.end()) { + LOG_DEBUG(http_logger, isc::log::DBGLVL_TRACE_BASIC, + HTTP_CLIENT_REQUEST_AUTHORIZED) + .arg(it->second); + return (HttpResponsePtr()); + } + 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()); + } + HttpResponsePtr response = + creator->createStockHttpResponse(request, HttpStatusCode::UNAUTHORIZED); + response->reset(); + response->context()->headers_.push_back( + HttpHeaderContext("WWW-Authenticate", + "Basic realm=\"" + realm + "\"")); + response->finalize(); + return (response); +} + +} // end of namespace isc::http +} // end of namespace isc diff --git a/src/lib/http/response_creator_auth.h b/src/lib/http/response_creator_auth.h new file mode 100644 index 0000000000..5cc085d071 --- /dev/null +++ b/src/lib/http/response_creator_auth.h @@ -0,0 +1,35 @@ +// Copyright (C) 2020 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef HTTP_RESPONSE_CREATOR_AUTH_H +#define HTTP_RESPONSE_CREATOR_AUTH_H + +#include +#include +#include + +namespace isc { +namespace http { + +/// @brief Type of basic HTTP authentication credential and user id map. +typedef std::unordered_map BasicHttpAuthMap; + +/// @brief Validate basic HTTP authentication. +/// +/// @param creator The HTTP response creator. +/// @param request The HTTP request to validate. +/// @param credentials Authorized credentials and user id map. +/// @param realm Realm name. +/// @return Error HTTP response if validation failed, null otherwise. +HttpResponsePtr checkBasicHttpAuth(HttpResponseCreatorPtr creator, + const ConstHttpRequestPtr& request, + const BasicHttpAuthMap& credentials, + const std::string& realm); + +} // end of namespace isc::http +} // end of namespace isc + +#endif // endif HTTP_RESPONSE_CREATOR_AUTH_H diff --git a/src/lib/http/tests/Makefile.am b/src/lib/http/tests/Makefile.am index 9ee3bd9bb6..e88d4dcccc 100644 --- a/src/lib/http/tests/Makefile.am +++ b/src/lib/http/tests/Makefile.am @@ -43,8 +43,9 @@ libhttp_unittests_CXXFLAGS = $(AM_CXXFLAGS) libhttp_unittests_LDFLAGS = $(AM_LDFLAGS) $(GTEST_LDFLAGS) libhttp_unittests_LDADD = $(top_builddir)/src/lib/http/libkea-http.la -libhttp_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la +libhttp_unittests_LDADD += $(top_builddir)/src/lib/testutils/libkea-testutils.la libhttp_unittests_LDADD += $(top_builddir)/src/lib/cc/libkea-cc.la +libhttp_unittests_LDADD += $(top_builddir)/src/lib/asiolink/libkea-asiolink.la libhttp_unittests_LDADD += $(top_builddir)/src/lib/log/libkea-log.la libhttp_unittests_LDADD += $(top_builddir)/src/lib/util/libkea-util.la libhttp_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la diff --git a/src/lib/http/tests/basic_auth_unittests.cc b/src/lib/http/tests/basic_auth_unittests.cc index 305e57fef7..1c2693d3a1 100644 --- a/src/lib/http/tests/basic_auth_unittests.cc +++ b/src/lib/http/tests/basic_auth_unittests.cc @@ -52,4 +52,14 @@ TEST(BasicHttpAuthTest, utf8) { EXPECT_EQ("Zm9vCjpiB3I=", basic_auth->getCredential()); } +// Test that a header context for basic HTTP authentication can be created. +TEST(BasicHttpAuthTest, headerContext) { + BasicHttpAuthPtr basic_auth; + EXPECT_NO_THROW(basic_auth.reset(new BasicHttpAuth("foo", "bar"))); + ASSERT_TRUE(basic_auth); + BasicAuthHttpHeaderContext ctx(*basic_auth); + EXPECT_EQ("Authorization", ctx.name_); + EXPECT_EQ("Basic Zm9vOmJhcg==", ctx.value_); +} + } // end of anonymous namespace diff --git a/src/lib/http/tests/response_creator_unittests.cc b/src/lib/http/tests/response_creator_unittests.cc index b9ad03da7b..5c65649a52 100644 --- a/src/lib/http/tests/response_creator_unittests.cc +++ b/src/lib/http/tests/response_creator_unittests.cc @@ -1,21 +1,26 @@ -// Copyright (C) 2016-2017 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2016-2020 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at http://mozilla.org/MPL/2.0/. #include +#include #include #include #include #include +#include #include #include +#include #include #include +using namespace isc::dhcp::test; using namespace isc::http; using namespace isc::http::test; +using namespace std; namespace { @@ -73,6 +78,9 @@ private: } }; +/// @brief Pointer to test HTTP response creator. +typedef boost::shared_ptr TestHttpResponseCreatorPtr; + // This test verifies that Bad Request status is generated when the request // hasn't been finalized. TEST(HttpResponseCreatorTest, badRequest) { @@ -123,4 +131,174 @@ TEST(HttpResponseCreatorTest, goodRequest) { response->toString()); } +/// @brief Test fixture for HTTP response creator authentication. +class HttpResponseCreatorAuthTest : public LogContentTest { }; + +// This test verifies that missing required authentication header gives +// unauthorized error. +TEST_F(HttpResponseCreatorAuthTest, noAuth) { + // 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"; + 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_TRUE(response); + + EXPECT_EQ("HTTP/1.0 401 Unauthorized\r\n" + "Content-Length: 41\r\n" + "Content-Type: application/json\r\n" + "Date: Tue, 19 Dec 2016 18:53:35 GMT\r\n" + "WWW-Authenticate: Basic realm=\"ISC.ORG\"\r\n\r\n" + "{ \"result\": 401, \"text\": \"Unauthorized\" }", + response->toString()); + + addString("HTTP_CLIENT_REQUEST_NO_AUTH_HEADER received HTTP request " + "without required authentication header"); + EXPECT_TRUE(checkFile()); +} + +// This test verifies that too short authentication header is rejected. +TEST_F(HttpResponseCreatorAuthTest, authTooShort) { + // 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 ="); + 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_TRUE(response); + + EXPECT_EQ("HTTP/1.0 401 Unauthorized\r\n" + "Content-Length: 41\r\n" + "Content-Type: application/json\r\n" + "Date: Tue, 19 Dec 2016 18:53:35 GMT\r\n" + "WWW-Authenticate: Basic realm=\"ISC.ORG\"\r\n\r\n" + "{ \"result\": 401, \"text\": \"Unauthorized\" }", + response->toString()); + + addString("HTTP_CLIENT_REQUEST_BAD_AUTH_HEADER received HTTP request " + "with malformed authentication header: " + "header content is too short"); + EXPECT_TRUE(checkFile()); +} + +// This test verifies that another authentication schema is rejected. +TEST_F(HttpResponseCreatorAuthTest, badScheme) { + // 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", "Basis 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_TRUE(response); + + EXPECT_EQ("HTTP/1.0 401 Unauthorized\r\n" + "Content-Length: 41\r\n" + "Content-Type: application/json\r\n" + "Date: Tue, 19 Dec 2016 18:53:35 GMT\r\n" + "WWW-Authenticate: Basic realm=\"ISC.ORG\"\r\n\r\n" + "{ \"result\": 401, \"text\": \"Unauthorized\" }", + response->toString()); + + addString("HTTP_CLIENT_REQUEST_BAD_AUTH_HEADER received HTTP request " + "with malformed authentication header: " + "not basic authentication"); + EXPECT_TRUE(checkFile()); +} + +// This test verifies that not matching credential is rejected. +TEST_F(HttpResponseCreatorAuthTest, notMatching) { + // 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=="); + 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_TRUE(response); + + EXPECT_EQ("HTTP/1.0 401 Unauthorized\r\n" + "Content-Length: 41\r\n" + "Content-Type: application/json\r\n" + "Date: Tue, 19 Dec 2016 18:53:35 GMT\r\n" + "WWW-Authenticate: Basic realm=\"ISC.ORG\"\r\n\r\n" + "{ \"result\": 401, \"text\": \"Unauthorized\" }", + response->toString()); + + addString("HTTP_CLIENT_REQUEST_NOT_AUTHORIZED received HTTP request " + "with not matching authentication header"); + EXPECT_TRUE(checkFile()); +} + +// This test verifies that matching credential is accepted. +TEST_F(HttpResponseCreatorAuthTest, matching) { + // 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)); + EXPECT_FALSE(response); + + addString("HTTP_CLIENT_REQUEST_AUTHORIZED received HTTP request " + "authorized for 'test'"); + EXPECT_TRUE(checkFile()); +} + } -- GitLab From b6ed7b23f46a7d925d6f2f4cff15f444886c5e27 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Sun, 12 Jul 2020 10:17:35 +0200 Subject: [PATCH 07/33] [#1304] Updated CA syntax --- src/bin/agent/agent_lexer.ll | 38 +++++++++++++++++ src/bin/agent/agent_parser.yy | 72 +++++++++++++++++++++++++++++++++ src/bin/agent/parser_context.cc | 6 ++- src/bin/agent/parser_context.h | 9 +++-- 4 files changed, 120 insertions(+), 5 deletions(-) diff --git a/src/bin/agent/agent_lexer.ll b/src/bin/agent/agent_lexer.ll index c4331a5b8e..70805ec4b7 100644 --- a/src/bin/agent/agent_lexer.ll +++ b/src/bin/agent/agent_lexer.ll @@ -200,11 +200,21 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence} } } +\"basic-authentication-realm\" { + switch(driver.ctx_) { + case ParserContext::AGENT: + return AgentParser::make_BASIC_AUTHENTICATION_REALM(driver.loc_); + default: + return AgentParser::make_STRING("basic-authentication-realm", driver.loc_); + } +} + \"user-context\" { switch(driver.ctx_) { case ParserContext::AGENT: case ParserContext::SERVER: case ParserContext::LOGGERS: + case ParserContext::BASIC_AUTHENTICATIONS: return AgentParser::make_USER_CONTEXT(driver.loc_); default: return AgentParser::make_STRING("user-context", driver.loc_); @@ -216,6 +226,7 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence} case ParserContext::AGENT: case ParserContext::SERVER: case ParserContext::LOGGERS: + case ParserContext::BASIC_AUTHENTICATIONS: return AgentParser::make_COMMENT(driver.loc_); default: return AgentParser::make_STRING("comment", driver.loc_); @@ -402,6 +413,33 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence} } } +\"basic-authentications\" { + switch(driver.ctx_) { + case ParserContext::AGENT: + return AgentParser::make_BASIC_AUTHENTICATIONS(driver.loc_); + default: + return AgentParser::make_STRING("basic-authentications", driver.loc_); + } +} + +\"user\" { + switch(driver.ctx_) { + case ParserContext::BASIC_AUTHENTICATIONS: + return AgentParser::make_USER(driver.loc_); + default: + return AgentParser::make_STRING("user", driver.loc_); + } +} + +\"password\" { + switch(driver.ctx_) { + case ParserContext::BASIC_AUTHENTICATIONS: + return AgentParser::make_PASSWORD(driver.loc_); + default: + return AgentParser::make_STRING("password", driver.loc_); + } +} + {JSONString} { /* A string has been matched. It contains the actual string and single quotes. We need to get those quotes out of the way and just use its content, e.g. diff --git a/src/bin/agent/agent_parser.yy b/src/bin/agent/agent_parser.yy index de1bf09212..84c435dd55 100644 --- a/src/bin/agent/agent_parser.yy +++ b/src/bin/agent/agent_parser.yy @@ -51,6 +51,7 @@ using namespace std; CONTROL_AGENT "Control-agent" HTTP_HOST "http-host" HTTP_PORT "http-port" + BASIC_AUTHENTICATION_REALM "basic-authentication-realm" USER_CONTEXT "user-context" COMMENT "comment" @@ -63,6 +64,10 @@ using namespace std; SOCKET_TYPE "socket-type" UNIX "unix" + BASIC_AUTHENTICATIONS "basic-authentications" + USER "user" + PASSWORD "password" + HOOKS_LIBRARIES "hooks-libraries" LIBRARY "library" PARAMETERS "parameters" @@ -260,7 +265,9 @@ global_params: global_param // Dhcp6. global_param: http_host | http_port + | basic_authentication_realm | control_sockets + | basic_authentications | hooks_libraries | loggers | user_context @@ -281,6 +288,14 @@ http_port: HTTP_PORT COLON INTEGER { ctx.stack_.back()->set("http-port", prf); }; +basic_authentication_realm: BASIC_AUTHENTICATION_REALM { + ctx.enter(ctx.NO_KEYWORDS); +} COLON STRING { + ElementPtr realm(new StringElement($4, ctx.loc2pos(@4))); + ctx.stack_.back()->set("basic-authentication-realm", realm); + ctx.leave(); +}; + user_context: USER_CONTEXT { ctx.enter(ctx.NO_KEYWORDS); } COLON map_value { @@ -481,6 +496,63 @@ socket_type_value : UNIX { $$ = ElementPtr(new StringElement("unix", ctx.loc2pos // --- control-sockets end here ------------------------------------------------ +// --- basic-authentications starts here ----------------------------------------------------- + +basic_authentications: BASIC_AUTHENTICATIONS { + ElementPtr l(new ListElement(ctx.loc2pos(@1))); + ctx.stack_.back()->set("basic-authentications", l); + ctx.stack_.push_back(l); + ctx.enter(ctx.BASIC_AUTHENTICATIONS); +} COLON LSQUARE_BRACKET basic_auth_list RSQUARE_BRACKET { + ctx.stack_.pop_back(); + ctx.leave(); +}; + +basic_auth_list: %empty + | not_empty_basic_auth_list + ; + +not_empty_basic_auth_list: basic_auth + | not_empty_basic_auth_list COMMA basic_auth + ; + +basic_auth: LCURLY_BRACKET { + ElementPtr m(new MapElement(ctx.loc2pos(@1))); + ctx.stack_.back()->add(m); + ctx.stack_.push_back(m); +} basic_auth_params RCURLY_BRACKET { + ctx.stack_.pop_back(); +}; + +basic_auth_params: basic_auth_param + | basic_auth_params COMMA basic_auth_param + ; + +basic_auth_param: user + | password + | user_context + | comment + | unknown_map_entry + ; + +user: USER { + ctx.enter(ctx.NO_KEYWORDS); +} COLON STRING { + ElementPtr user(new StringElement($4, ctx.loc2pos(@4))); + ctx.stack_.back()->set("user", user); + ctx.leave(); +}; + +password: PASSWORD { + ctx.enter(ctx.NO_KEYWORDS); +} COLON STRING { + ElementPtr password(new StringElement($4, ctx.loc2pos(@4))); + ctx.stack_.back()->set("password", password); + ctx.leave(); +}; + +// --- basic-authentications end here ----------------------------------------------------- + // --- Loggers starts here ----------------------------------------------------- loggers: LOGGERS { diff --git a/src/bin/agent/parser_context.cc b/src/bin/agent/parser_context.cc index 1c48fc0cd9..3517252645 100644 --- a/src/bin/agent/parser_context.cc +++ b/src/bin/agent/parser_context.cc @@ -135,10 +135,12 @@ ParserContext::contextName() return ("loggers"); case OUTPUT_OPTIONS: return ("output-options"); + case BASIC_AUTHENTICATIONS: + return ("basic-authentications"); default: return ("__unknown__"); } } -}; -}; +} // end of isc::eval namespace +} // end of isc namespace diff --git a/src/bin/agent/parser_context.h b/src/bin/agent/parser_context.h index d03dd0e41c..32572f669a 100644 --- a/src/bin/agent/parser_context.h +++ b/src/bin/agent/parser_context.h @@ -174,7 +174,10 @@ public: LOGGERS, ///< Used while parsing Control-agent/loggers/output_options structures. - OUTPUT_OPTIONS + OUTPUT_OPTIONS, + + ///< Used while parsing Control-agent/basic-authentications. + BASIC_AUTHENTICATIONS } LexerContext; @@ -258,7 +261,7 @@ public: isc::data::ElementPtr parseCommon(); }; -}; // end of isc::eval namespace -}; // end of isc namespace +} // end of isc::eval namespace +} // end of isc namespace #endif -- GitLab From b7f239885d1b8ab479d86854e84664ea271fbc46 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Sun, 12 Jul 2020 08:20:35 +0000 Subject: [PATCH 08/33] [#1304] Regen flex and bison --- src/bin/agent/agent_lexer.cc | 1420 ++++++++++++++++++--------------- src/bin/agent/agent_parser.cc | 997 +++++++++++++---------- src/bin/agent/agent_parser.h | 467 ++++++----- 3 files changed, 1608 insertions(+), 1276 deletions(-) diff --git a/src/bin/agent/agent_lexer.cc b/src/bin/agent/agent_lexer.cc index 9f0410534d..d052cc765c 100644 --- a/src/bin/agent/agent_lexer.cc +++ b/src/bin/agent/agent_lexer.cc @@ -691,8 +691,8 @@ static void yynoreturn yy_fatal_error ( const char* msg ); /* %% [3.0] code to copy yytext_ptr to yytext[] goes here, if %array \ */\ (yy_c_buf_p) = yy_cp; /* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */ -#define YY_NUM_RULES 55 -#define YY_END_OF_BUFFER 56 +#define YY_NUM_RULES 59 +#define YY_END_OF_BUFFER 60 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -700,42 +700,46 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static const flex_int16_t yy_accept[305] = +static const flex_int16_t yy_accept[342] = { 0, - 48, 48, 0, 0, 0, 0, 0, 0, 0, 0, - 56, 54, 10, 11, 54, 1, 48, 45, 48, 48, - 54, 47, 46, 54, 54, 54, 54, 54, 41, 42, - 54, 54, 54, 43, 44, 5, 5, 5, 54, 54, - 54, 10, 11, 0, 0, 37, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 48, 48, 0, 47, 48, 3, 2, 6, 0, 48, - 0, 0, 0, 0, 0, 0, 4, 0, 0, 9, - 0, 38, 0, 0, 0, 40, 0, 0, 0, 0, + 52, 52, 0, 0, 0, 0, 0, 0, 0, 0, + 60, 58, 10, 11, 58, 1, 52, 49, 52, 52, + 58, 51, 50, 58, 58, 58, 58, 58, 45, 46, + 58, 58, 58, 47, 48, 5, 5, 5, 58, 58, + 58, 10, 11, 0, 0, 41, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 52, 52, 0, 51, 52, 3, 2, 6, 0, + 52, 0, 0, 0, 0, 0, 0, 4, 0, 0, + 9, 0, 42, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, - 0, 0, 8, 0, 0, 0, 39, 0, 0, 0, - 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 53, 51, - 0, 50, 49, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 8, 0, 0, 0, 43, 0, + 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 57, 55, 0, 54, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 52, 49, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 28, 0, 0, 0, 0, 0, - 23, 0, 0, 0, 0, 0, 0, 0, 18, 19, - - 31, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 7, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 33, 30, 0, 0, 0, - 0, 0, 0, 0, 16, 0, 0, 0, 0, 0, - 25, 27, 32, 0, 0, 34, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 36, 0, - 0, 0, 0, 0, 0, 0, 13, 14, 0, 0, - 0, 0, 0, 0, 0, 35, 0, 0, 26, 0, - 0, 0, 0, 0, 0, 0, 21, 22, 0, 0, - 0, 0, 0, 15, 12, 0, 0, 0, 0, 0, - - 29, 17, 24, 0 + 0, 0, 56, 53, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 29, 0, 0, 0, 0, 0, 0, 24, 39, + + 0, 0, 0, 0, 0, 0, 0, 0, 19, 20, + 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 34, 31, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, + 0, 0, 0, 0, 26, 28, 33, 0, 0, 0, + 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 40, 37, 0, 0, 0, 0, + 0, 0, 0, 0, 13, 14, 0, 0, 0, 0, + 0, 0, 0, 0, 36, 0, 0, 27, 0, 0, + + 0, 0, 0, 0, 0, 0, 22, 23, 0, 0, + 0, 0, 0, 0, 16, 12, 0, 0, 0, 0, + 0, 0, 0, 30, 0, 18, 25, 0, 0, 0, + 0, 0, 0, 0, 38, 0, 0, 0, 0, 15, + 0 } ; static const YY_CHAR yy_ec[256] = @@ -752,8 +756,8 @@ static const YY_CHAR yy_ec[256] = 33, 34, 35, 5, 36, 5, 37, 38, 39, 40, 41, 42, 43, 44, 45, 5, 46, 47, 48, 49, - 50, 51, 5, 52, 53, 54, 55, 56, 5, 57, - 58, 59, 60, 5, 61, 5, 5, 5, 5, 5, + 50, 51, 5, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 5, 62, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, @@ -770,7 +774,7 @@ static const YY_CHAR yy_ec[256] = 5, 5, 5, 5, 5 } ; -static const YY_CHAR yy_meta[62] = +static const YY_CHAR yy_meta[63] = { 0, 1, 1, 2, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 3, 3, 3, @@ -778,315 +782,353 @@ static const YY_CHAR yy_meta[62] = 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3 + 3, 3 } ; -static const flex_int16_t yy_base[317] = +static const flex_int16_t yy_base[354] = { 0, - 0, 0, 60, 63, 66, 0, 64, 68, 48, 65, - 320, 1969, 85, 296, 127, 0, 107, 1969, 122, 127, - 82, 169, 1969, 274, 89, 80, 80, 102, 1969, 1969, - 103, 117, 121, 1969, 1969, 1969, 112, 277, 211, 0, - 236, 151, 248, 112, 156, 1969, 186, 185, 194, 201, - 212, 223, 246, 252, 260, 266, 273, 281, 300, 0, - 302, 321, 341, 349, 353, 1969, 0, 1969, 216, 297, - 118, 152, 138, 174, 223, 209, 1969, 199, 211, 1969, - 237, 1969, 366, 339, 206, 379, 408, 395, 404, 434, - 450, 456, 463, 472, 480, 490, 497, 514, 506, 533, - - 540, 549, 555, 563, 0, 235, 251, 181, 251, 258, - 267, 164, 1969, 0, 569, 203, 1969, 610, 605, 575, - 1969, 611, 640, 653, 659, 666, 674, 680, 693, 701, - 709, 718, 727, 735, 756, 762, 769, 268, 1969, 1969, - 298, 1969, 1969, 153, 0, 776, 815, 782, 791, 843, - 857, 863, 869, 877, 892, 898, 907, 913, 922, 932, - 942, 957, 966, 972, 978, 991, 1969, 1969, 165, 0, - 1002, 1039, 1008, 1025, 1037, 1014, 1066, 1084, 1090, 1096, - 1102, 1108, 1114, 1125, 1969, 1131, 1149, 1155, 1161, 1168, - 1969, 1178, 123, 0, 1185, 1191, 1197, 1207, 1969, 1969, - - 1969, 1227, 1233, 1248, 1254, 1262, 1269, 1275, 1283, 1289, - 1298, 1305, 1319, 1332, 1969, 1339, 1354, 1361, 1368, 1374, - 1383, 1391, 1397, 1403, 1410, 1969, 1969, 1420, 1426, 1432, - 1439, 1445, 1455, 1474, 1969, 1462, 1480, 1489, 1499, 1516, - 1969, 1969, 1969, 1523, 1529, 1969, 1535, 1541, 1553, 1559, - 1565, 1582, 1588, 1594, 1600, 1617, 1623, 1635, 1969, 1641, - 1647, 1653, 1659, 1665, 1677, 1689, 1969, 1969, 1700, 1706, - 1712, 1718, 1726, 1735, 1741, 1969, 1748, 1755, 1969, 1761, - 1770, 1790, 1796, 1805, 1811, 1817, 1969, 1969, 1825, 1831, - 1846, 1852, 1861, 1969, 1969, 1867, 1873, 1881, 1888, 1896, - - 1969, 1969, 1969, 1969, 1930, 1935, 1940, 1945, 1950, 1955, - 1960, 1963, 155, 151, 91, 83 + 0, 0, 61, 64, 67, 0, 65, 69, 49, 66, + 317, 2235, 86, 312, 129, 0, 108, 2235, 125, 129, + 83, 171, 2235, 291, 90, 81, 81, 86, 2235, 2235, + 97, 119, 123, 2235, 2235, 2235, 153, 288, 251, 0, + 278, 154, 294, 83, 158, 2235, 188, 159, 197, 203, + 214, 222, 238, 244, 259, 265, 273, 279, 302, 308, + 0, 304, 310, 323, 348, 333, 2235, 0, 2235, 339, + 352, 100, 180, 163, 183, 205, 187, 2235, 256, 285, + 2235, 215, 2235, 364, 377, 281, 389, 413, 406, 398, + 442, 455, 461, 467, 476, 482, 496, 503, 511, 517, + + 526, 537, 547, 553, 560, 572, 0, 206, 216, 210, + 224, 237, 232, 236, 2235, 0, 582, 227, 2235, 623, + 596, 608, 616, 2235, 623, 652, 665, 671, 678, 686, + 692, 705, 713, 721, 730, 739, 747, 768, 774, 781, + 788, 245, 2235, 2235, 265, 2235, 2235, 171, 0, 794, + 833, 804, 810, 828, 862, 875, 881, 887, 896, 910, + 916, 925, 931, 940, 950, 960, 975, 984, 990, 996, + 1009, 1020, 2235, 2235, 162, 0, 1032, 1069, 1038, 1054, + 1062, 1068, 1044, 1098, 1115, 1122, 1128, 1134, 1140, 1149, + 1163, 2235, 1157, 1179, 1187, 1193, 1199, 1216, 2235, 2235, + + 1222, 140, 0, 1228, 1237, 1245, 1251, 1262, 2235, 2235, + 2235, 1275, 1281, 1287, 1299, 1310, 1323, 1317, 1333, 1339, + 1346, 1353, 1369, 1375, 1382, 2235, 1388, 1394, 1404, 1418, + 1411, 1424, 1434, 1440, 1454, 1460, 1469, 2235, 2235, 1475, + 1483, 1494, 1504, 1510, 1517, 1529, 1539, 1546, 2235, 1552, + 1558, 1581, 1587, 1595, 2235, 2235, 2235, 1601, 1608, 1621, + 2235, 1630, 1637, 1644, 1655, 1664, 1674, 1680, 1689, 1698, + 1709, 1718, 1725, 1732, 2235, 2235, 1738, 1754, 1761, 1767, + 1775, 1781, 1788, 1797, 2235, 2235, 1811, 1823, 1834, 1840, + 1846, 1852, 1858, 1864, 2235, 1881, 1887, 2235, 1893, 1910, + + 1916, 1922, 1928, 1937, 1945, 1951, 2235, 2235, 1957, 1963, + 1971, 1986, 1992, 2000, 2235, 2235, 2007, 2016, 2022, 2029, + 2036, 2042, 2056, 2235, 2065, 2235, 2235, 2076, 2082, 2090, + 2100, 2106, 2112, 2125, 2235, 2135, 2141, 2148, 2159, 2235, + 2235, 2196, 2201, 2206, 2211, 2216, 2221, 2226, 2229, 157, + 143, 121, 92 } ; -static const flex_int16_t yy_def[317] = +static const flex_int16_t yy_def[354] = { 0, - 304, 1, 305, 305, 1, 5, 5, 5, 5, 5, - 304, 304, 304, 304, 306, 307, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 308, - 304, 304, 304, 309, 306, 304, 306, 310, 306, 306, - 306, 306, 306, 306, 306, 306, 306, 306, 306, 307, - 304, 304, 304, 304, 304, 304, 311, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 308, 304, - 309, 304, 304, 306, 312, 306, 310, 306, 306, 306, - 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, - - 306, 306, 306, 306, 311, 304, 304, 304, 304, 304, - 304, 304, 304, 313, 306, 312, 304, 310, 306, 306, - 304, 306, 306, 306, 306, 306, 306, 306, 306, 306, - 306, 306, 306, 306, 306, 306, 306, 304, 304, 304, - 304, 304, 304, 304, 314, 306, 310, 306, 306, 306, - 306, 306, 306, 306, 306, 306, 306, 306, 306, 306, - 306, 306, 306, 306, 306, 306, 304, 304, 304, 315, - 306, 310, 306, 306, 306, 306, 306, 306, 306, 306, - 306, 306, 306, 306, 304, 306, 306, 306, 306, 306, - 304, 306, 304, 316, 306, 306, 306, 306, 304, 304, - - 304, 306, 306, 306, 306, 306, 306, 306, 306, 306, - 306, 306, 306, 306, 304, 306, 306, 306, 306, 306, - 306, 306, 306, 306, 306, 304, 304, 306, 306, 306, - 306, 306, 306, 306, 304, 306, 306, 306, 306, 306, - 304, 304, 304, 306, 306, 304, 306, 306, 306, 306, - 306, 306, 306, 306, 306, 306, 306, 306, 304, 306, - 306, 306, 306, 306, 306, 306, 304, 304, 306, 306, - 306, 306, 306, 306, 306, 304, 306, 306, 304, 306, - 306, 306, 306, 306, 306, 306, 304, 304, 306, 306, - 306, 306, 306, 304, 304, 306, 306, 306, 306, 306, - - 304, 304, 304, 0, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304 + 341, 1, 342, 342, 1, 5, 5, 5, 5, 5, + 341, 341, 341, 341, 343, 344, 341, 341, 341, 341, + 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, + 341, 341, 341, 341, 341, 341, 341, 341, 341, 345, + 341, 341, 341, 346, 343, 341, 343, 347, 343, 343, + 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, + 344, 341, 341, 341, 341, 341, 341, 348, 341, 341, + 341, 341, 341, 341, 341, 341, 341, 341, 341, 345, + 341, 346, 341, 341, 343, 349, 343, 347, 343, 343, + 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, + + 343, 343, 343, 343, 343, 343, 348, 341, 341, 341, + 341, 341, 341, 341, 341, 350, 343, 349, 341, 347, + 343, 343, 343, 341, 343, 343, 343, 343, 343, 343, + 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, + 343, 341, 341, 341, 341, 341, 341, 341, 351, 343, + 347, 343, 343, 343, 343, 343, 343, 343, 343, 343, + 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, + 343, 343, 341, 341, 341, 352, 343, 347, 343, 343, + 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, + 343, 341, 343, 343, 343, 343, 343, 343, 341, 341, + + 343, 341, 353, 343, 343, 343, 343, 343, 341, 341, + 341, 343, 343, 343, 343, 343, 343, 343, 343, 343, + 343, 343, 343, 343, 343, 341, 343, 343, 343, 343, + 343, 343, 343, 343, 343, 343, 343, 341, 341, 343, + 343, 343, 343, 343, 343, 343, 343, 343, 341, 343, + 343, 343, 343, 343, 341, 341, 341, 343, 343, 343, + 341, 343, 343, 343, 343, 343, 343, 343, 343, 343, + 343, 343, 343, 343, 341, 341, 343, 343, 343, 343, + 343, 343, 343, 343, 341, 341, 343, 343, 343, 343, + 343, 343, 343, 343, 341, 343, 343, 341, 343, 343, + + 343, 343, 343, 343, 343, 343, 341, 341, 343, 343, + 343, 343, 343, 343, 341, 341, 343, 343, 343, 343, + 343, 343, 343, 341, 343, 341, 341, 343, 343, 343, + 343, 343, 343, 343, 341, 343, 343, 343, 343, 341, + 0, 341, 341, 341, 341, 341, 341, 341, 341, 341, + 341, 341, 341 } ; -static const flex_int16_t yy_nxt[2031] = +static const flex_int16_t yy_nxt[2298] = { 0, 12, 13, 14, 13, 12, 15, 16, 12, 17, 18, 19, 20, 21, 22, 22, 22, 22, 23, 24, 12, 12, 12, 12, 12, 25, 26, 12, 27, 12, 12, 28, 12, 29, 12, 30, 12, 12, 12, 12, 12, 25, 31, 12, 12, 12, 12, 12, 12, 32, 12, - 12, 12, 12, 33, 12, 12, 12, 12, 12, 34, - 35, 37, 14, 37, 37, 14, 37, 38, 41, 40, - 38, 12, 12, 40, 12, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 41, 42, 81, 42, 66, - 12, 12, 12, 12, 67, 194, 12, 69, 12, 69, - - 12, 71, 70, 70, 70, 70, 12, 12, 12, 12, - 39, 72, 12, 42, 12, 42, 71, 82, 61, 12, - 62, 62, 62, 62, 71, 12, 12, 44, 44, 44, - 73, 63, 46, 61, 72, 64, 64, 64, 64, 74, - 65, 65, 65, 65, 106, 83, 63, 63, 72, 73, - 47, 63, 42, 73, 42, 170, 44, 44, 44, 145, - 48, 46, 63, 215, 106, 49, 50, 63, 51, 108, - 52, 75, 76, 53, 54, 55, 56, 57, 107, 58, - 61, 59, 64, 64, 64, 64, 44, 44, 44, 48, - 86, 46, 108, 63, 44, 44, 44, 45, 107, 46, - - 106, 44, 44, 44, 193, 140, 46, 169, 117, 63, - 144, 117, 44, 44, 44, 89, 113, 46, 45, 48, - 109, 140, 45, 44, 44, 44, 45, 48, 46, 70, - 70, 70, 70, 45, 48, 84, 45, 112, 45, 87, - 108, 90, 82, 88, 91, 48, 44, 44, 44, 107, - 43, 46, 44, 44, 44, 80, 48, 46, 92, 78, - 44, 44, 44, 111, 138, 46, 44, 44, 44, 110, - 83, 46, 93, 44, 44, 44, 94, 139, 46, 48, - 138, 44, 44, 44, 139, 48, 46, 138, 97, 77, - 95, 140, 167, 48, 68, 96, 98, 139, 43, 48, - - 44, 44, 44, 141, 142, 46, 48, 143, 167, 100, - 70, 70, 70, 70, 48, 65, 65, 65, 65, 304, - 99, 101, 167, 304, 304, 304, 63, 304, 304, 304, - 102, 304, 61, 48, 62, 62, 62, 62, 168, 44, - 44, 44, 63, 304, 46, 63, 304, 304, 103, 69, - 304, 69, 104, 304, 70, 70, 70, 70, 304, 304, - 61, 63, 64, 64, 64, 64, 65, 65, 65, 65, - 304, 81, 48, 63, 304, 304, 304, 63, 81, 44, - 44, 44, 304, 304, 46, 304, 304, 115, 304, 63, - 304, 304, 304, 63, 304, 44, 44, 44, 304, 81, - - 46, 304, 304, 81, 44, 44, 44, 81, 304, 121, - 304, 304, 48, 304, 81, 304, 304, 81, 304, 81, - 114, 118, 118, 118, 118, 304, 304, 304, 48, 118, - 118, 118, 118, 118, 44, 44, 44, 48, 304, 46, - 304, 304, 119, 120, 118, 118, 118, 118, 118, 118, - 44, 44, 44, 304, 304, 46, 44, 44, 44, 304, - 304, 46, 304, 44, 44, 44, 304, 48, 46, 304, - 304, 122, 44, 44, 44, 304, 304, 46, 304, 304, - 44, 44, 44, 48, 304, 46, 304, 304, 123, 48, - 44, 44, 44, 304, 304, 46, 48, 44, 44, 44, - - 304, 304, 46, 304, 304, 48, 44, 44, 44, 304, - 124, 46, 125, 48, 44, 44, 44, 127, 304, 46, - 304, 304, 304, 48, 304, 126, 304, 304, 304, 304, - 48, 304, 128, 44, 44, 44, 304, 304, 46, 48, - 44, 44, 44, 304, 304, 46, 304, 48, 304, 44, - 44, 44, 304, 129, 46, 44, 44, 44, 304, 131, - 46, 130, 304, 44, 44, 44, 48, 304, 46, 44, - 44, 44, 304, 48, 46, 44, 44, 44, 304, 304, - 46, 304, 48, 304, 132, 304, 133, 135, 48, 304, - 304, 304, 304, 304, 304, 134, 48, 304, 304, 136, - - 304, 304, 48, 137, 304, 44, 44, 44, 48, 304, - 46, 44, 44, 44, 304, 304, 46, 304, 304, 304, - 304, 304, 146, 147, 147, 147, 147, 304, 149, 304, - 304, 147, 147, 147, 147, 147, 304, 304, 48, 304, - 44, 44, 44, 304, 48, 46, 147, 147, 147, 147, - 147, 147, 148, 44, 44, 44, 304, 304, 46, 44, - 44, 44, 304, 304, 46, 150, 44, 44, 44, 304, - 304, 46, 304, 48, 44, 44, 44, 304, 304, 46, - 44, 44, 44, 304, 304, 46, 48, 304, 304, 304, - 151, 304, 48, 44, 44, 44, 304, 304, 46, 48, - - 304, 44, 44, 44, 153, 152, 46, 48, 304, 44, - 44, 44, 304, 48, 46, 304, 154, 304, 44, 44, - 44, 304, 156, 46, 304, 155, 48, 44, 44, 44, - 304, 304, 46, 304, 48, 44, 44, 44, 304, 304, - 46, 159, 48, 304, 304, 157, 304, 304, 158, 304, - 304, 48, 304, 304, 161, 304, 44, 44, 44, 160, - 48, 46, 44, 44, 44, 304, 304, 46, 48, 44, - 44, 44, 304, 304, 46, 163, 44, 44, 44, 304, - 162, 46, 44, 44, 44, 304, 304, 46, 304, 48, - 304, 44, 44, 44, 304, 48, 46, 304, 304, 304, - - 304, 164, 48, 304, 304, 304, 304, 304, 304, 48, - 304, 304, 304, 304, 304, 48, 304, 304, 165, 304, - 166, 304, 173, 304, 48, 304, 304, 171, 172, 172, - 172, 172, 304, 304, 304, 304, 172, 172, 172, 172, - 172, 304, 174, 44, 44, 44, 304, 304, 46, 304, - 304, 172, 172, 172, 172, 172, 172, 44, 44, 44, - 304, 304, 46, 44, 44, 44, 304, 304, 46, 44, - 44, 44, 176, 177, 46, 304, 48, 44, 44, 44, - 304, 304, 46, 304, 304, 175, 304, 180, 304, 304, - 48, 304, 44, 44, 44, 304, 48, 46, 44, 44, - - 44, 304, 48, 46, 304, 304, 178, 44, 44, 44, - 48, 304, 46, 44, 44, 44, 304, 304, 46, 304, - 304, 179, 44, 44, 44, 48, 304, 185, 181, 304, - 304, 48, 44, 44, 44, 304, 304, 46, 182, 304, - 48, 304, 44, 44, 44, 304, 48, 46, 304, 304, - 304, 183, 304, 184, 304, 48, 304, 44, 44, 44, - 304, 304, 46, 304, 304, 48, 44, 44, 44, 304, - 304, 46, 44, 44, 44, 48, 304, 46, 44, 44, - 44, 304, 304, 191, 304, 304, 186, 304, 304, 187, - 48, 44, 44, 44, 304, 304, 46, 188, 304, 48, - - 304, 192, 44, 44, 44, 48, 304, 46, 44, 44, - 44, 48, 190, 46, 44, 44, 44, 189, 304, 199, - 304, 304, 304, 304, 48, 44, 44, 44, 304, 304, - 46, 304, 304, 304, 304, 48, 304, 44, 44, 44, - 304, 48, 46, 304, 304, 304, 304, 48, 304, 304, - 304, 195, 45, 45, 45, 45, 196, 304, 48, 304, - 45, 45, 45, 45, 45, 304, 44, 44, 44, 304, - 48, 200, 304, 304, 197, 45, 45, 45, 45, 45, - 45, 304, 304, 198, 44, 44, 44, 304, 304, 201, - 44, 44, 44, 304, 304, 46, 44, 44, 44, 48, - - 202, 46, 44, 44, 44, 304, 304, 46, 44, 44, - 44, 304, 304, 46, 44, 44, 44, 48, 304, 46, - 304, 304, 304, 48, 304, 44, 44, 44, 304, 48, - 46, 44, 44, 44, 304, 48, 46, 304, 304, 203, - 304, 48, 304, 304, 304, 304, 204, 48, 304, 44, - 44, 44, 304, 205, 46, 44, 44, 44, 48, 206, - 46, 44, 44, 44, 48, 304, 46, 304, 44, 44, - 44, 304, 207, 46, 304, 304, 208, 304, 44, 44, - 44, 304, 48, 46, 209, 44, 44, 44, 48, 210, - 46, 44, 44, 44, 48, 304, 46, 44, 44, 44, - - 304, 48, 46, 304, 304, 212, 211, 44, 44, 44, - 304, 48, 46, 304, 304, 304, 214, 304, 48, 304, - 304, 213, 304, 304, 48, 304, 304, 44, 44, 44, - 48, 216, 46, 44, 44, 44, 304, 304, 46, 304, - 48, 304, 304, 218, 217, 304, 304, 219, 44, 44, - 44, 304, 304, 46, 44, 44, 44, 304, 304, 46, - 48, 304, 44, 44, 44, 304, 48, 46, 304, 44, - 44, 44, 304, 220, 46, 44, 44, 44, 304, 304, - 226, 48, 221, 44, 44, 44, 304, 48, 227, 44, - 44, 44, 304, 304, 46, 48, 304, 222, 44, 44, - - 44, 304, 48, 46, 304, 44, 44, 44, 48, 225, - 46, 223, 304, 304, 224, 304, 48, 304, 228, 44, - 44, 44, 48, 304, 46, 304, 304, 304, 304, 232, - 304, 48, 44, 44, 44, 304, 304, 46, 48, 44, - 44, 44, 229, 304, 46, 304, 230, 304, 304, 234, - 304, 304, 48, 304, 44, 44, 44, 304, 231, 235, - 304, 44, 44, 44, 304, 48, 46, 304, 44, 44, - 44, 236, 48, 46, 44, 44, 44, 304, 304, 46, - 304, 233, 304, 44, 44, 44, 304, 48, 46, 304, - 304, 44, 44, 44, 48, 304, 46, 44, 44, 44, - - 304, 48, 241, 44, 44, 44, 304, 48, 242, 304, - 44, 44, 44, 304, 304, 243, 48, 304, 238, 304, - 44, 44, 44, 237, 48, 46, 44, 44, 44, 304, - 48, 46, 44, 44, 44, 239, 48, 246, 304, 44, - 44, 44, 240, 48, 46, 44, 44, 44, 304, 304, - 46, 304, 304, 48, 304, 44, 44, 44, 304, 48, - 46, 304, 44, 44, 44, 48, 245, 46, 304, 244, - 304, 304, 48, 304, 44, 44, 44, 304, 48, 46, - 44, 44, 44, 304, 304, 46, 304, 304, 48, 44, - 44, 44, 304, 248, 46, 48, 247, 304, 249, 44, - - 44, 44, 304, 250, 46, 304, 304, 48, 304, 304, - 251, 304, 304, 48, 252, 304, 44, 44, 44, 304, - 253, 46, 48, 44, 44, 44, 254, 304, 46, 44, - 44, 44, 48, 304, 46, 44, 44, 44, 304, 304, - 259, 44, 44, 44, 304, 304, 46, 304, 304, 48, - 304, 304, 255, 44, 44, 44, 48, 304, 46, 44, - 44, 44, 48, 304, 46, 44, 44, 44, 48, 256, - 46, 304, 304, 257, 48, 304, 304, 260, 304, 304, - 258, 304, 44, 44, 44, 304, 48, 46, 44, 44, - 44, 304, 48, 46, 44, 44, 44, 304, 48, 46, - - 44, 44, 44, 304, 304, 267, 304, 263, 304, 304, - 261, 304, 262, 304, 304, 48, 304, 44, 44, 44, - 304, 48, 268, 44, 44, 44, 304, 48, 46, 304, - 304, 264, 304, 48, 265, 44, 44, 44, 304, 304, - 46, 44, 44, 44, 304, 266, 46, 44, 44, 44, - 48, 304, 46, 44, 44, 44, 48, 304, 46, 44, - 44, 44, 304, 304, 46, 44, 44, 44, 48, 304, - 46, 304, 304, 304, 48, 304, 269, 44, 44, 44, - 48, 304, 276, 304, 304, 304, 48, 270, 271, 44, - 44, 44, 48, 273, 46, 304, 304, 272, 48, 274, - - 44, 44, 44, 275, 304, 46, 44, 44, 44, 304, - 48, 279, 44, 44, 44, 304, 304, 46, 44, 44, - 44, 304, 48, 46, 304, 277, 44, 44, 44, 304, - 304, 46, 304, 48, 304, 44, 44, 44, 304, 48, - 46, 44, 44, 44, 278, 48, 46, 304, 44, 44, - 44, 48, 280, 46, 304, 44, 44, 44, 281, 48, - 46, 44, 44, 44, 304, 304, 287, 304, 48, 304, - 44, 44, 44, 304, 48, 288, 304, 304, 304, 304, - 304, 48, 282, 283, 304, 304, 284, 304, 48, 304, - 44, 44, 44, 304, 48, 46, 44, 44, 44, 285, - - 304, 46, 304, 48, 286, 44, 44, 44, 304, 304, - 46, 44, 44, 44, 304, 304, 46, 44, 44, 44, - 304, 304, 46, 48, 304, 44, 44, 44, 304, 48, - 294, 44, 44, 44, 304, 304, 295, 304, 48, 304, - 304, 304, 304, 289, 48, 291, 44, 44, 44, 290, - 48, 46, 44, 44, 44, 292, 304, 46, 48, 304, - 304, 44, 44, 44, 48, 293, 46, 44, 44, 44, - 304, 304, 46, 44, 44, 44, 304, 304, 46, 48, - 304, 44, 44, 44, 304, 48, 301, 304, 44, 44, - 44, 304, 297, 302, 48, 304, 44, 44, 44, 296, - - 48, 303, 304, 304, 304, 304, 48, 304, 304, 304, - 304, 304, 304, 298, 48, 304, 304, 304, 304, 299, - 304, 48, 304, 304, 304, 300, 304, 304, 304, 48, - 36, 36, 36, 36, 36, 45, 45, 45, 45, 45, - 60, 304, 60, 60, 60, 79, 304, 79, 304, 79, - 81, 81, 81, 81, 81, 85, 85, 85, 85, 85, - 105, 304, 105, 105, 105, 116, 116, 116, 11, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304 + 12, 12, 12, 33, 12, 12, 12, 12, 12, 12, + 34, 35, 37, 14, 37, 37, 14, 37, 38, 41, + 40, 38, 12, 12, 40, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 41, 42, 83, 42, + 67, 12, 12, 12, 12, 68, 82, 12, 70, 12, + + 70, 12, 72, 71, 71, 71, 71, 12, 12, 12, + 12, 39, 73, 12, 74, 12, 84, 72, 72, 62, + 12, 63, 63, 63, 63, 203, 108, 12, 12, 44, + 44, 44, 64, 75, 46, 73, 62, 74, 65, 65, + 65, 65, 66, 66, 66, 66, 108, 176, 64, 64, + 73, 74, 47, 64, 42, 42, 42, 42, 44, 44, + 44, 149, 48, 46, 87, 64, 49, 50, 51, 64, + 52, 45, 53, 76, 77, 54, 55, 56, 57, 58, + 226, 59, 62, 60, 65, 65, 65, 65, 44, 44, + 44, 48, 45, 46, 110, 64, 45, 44, 44, 44, + + 45, 202, 46, 44, 44, 44, 109, 45, 46, 108, + 45, 64, 45, 88, 44, 44, 44, 110, 110, 46, + 83, 48, 44, 44, 44, 175, 109, 46, 91, 111, + 48, 109, 119, 89, 144, 142, 48, 85, 44, 44, + 44, 113, 143, 46, 44, 44, 44, 48, 84, 46, + 144, 112, 90, 142, 92, 48, 144, 93, 142, 44, + 44, 44, 143, 143, 46, 44, 44, 44, 94, 173, + 46, 48, 147, 44, 44, 44, 145, 48, 46, 44, + 44, 44, 148, 146, 46, 173, 119, 95, 97, 173, + 115, 96, 48, 98, 114, 99, 43, 81, 48, 79, + + 78, 100, 44, 44, 44, 174, 48, 46, 44, 44, + 44, 69, 48, 46, 43, 102, 341, 66, 66, 66, + 66, 62, 341, 63, 63, 63, 63, 101, 64, 341, + 341, 70, 341, 70, 64, 48, 71, 71, 71, 71, + 341, 48, 103, 341, 64, 341, 66, 66, 66, 66, + 64, 104, 71, 71, 71, 71, 105, 64, 341, 62, + 106, 65, 65, 65, 65, 71, 71, 71, 71, 82, + 341, 341, 64, 64, 341, 341, 82, 44, 44, 44, + 341, 341, 46, 341, 341, 341, 341, 341, 64, 44, + 44, 44, 341, 341, 46, 341, 341, 82, 44, 44, + + 44, 82, 341, 46, 341, 82, 44, 44, 44, 341, + 48, 46, 82, 341, 341, 82, 341, 82, 116, 341, + 341, 341, 48, 341, 341, 117, 120, 120, 120, 120, + 341, 48, 341, 341, 120, 120, 120, 120, 120, 48, + 341, 341, 44, 44, 44, 122, 123, 124, 341, 120, + 120, 120, 120, 120, 120, 44, 44, 44, 121, 341, + 46, 44, 44, 44, 341, 341, 46, 44, 44, 44, + 341, 341, 46, 341, 341, 48, 44, 44, 44, 341, + 341, 46, 44, 44, 44, 341, 341, 46, 48, 341, + 341, 341, 125, 341, 48, 341, 44, 44, 44, 126, + + 48, 46, 341, 44, 44, 44, 341, 341, 46, 48, + 341, 44, 44, 44, 341, 48, 46, 44, 44, 44, + 341, 127, 46, 341, 341, 128, 44, 44, 44, 48, + 341, 46, 341, 130, 341, 129, 48, 44, 44, 44, + 341, 341, 46, 341, 48, 131, 341, 44, 44, 44, + 48, 341, 46, 44, 44, 44, 341, 341, 46, 48, + 44, 44, 44, 341, 133, 46, 341, 341, 132, 341, + 48, 341, 44, 44, 44, 341, 341, 46, 341, 134, + 48, 341, 44, 44, 44, 341, 48, 46, 135, 136, + 137, 139, 341, 48, 341, 341, 44, 44, 44, 341, + + 341, 46, 138, 341, 140, 48, 341, 341, 44, 44, + 44, 341, 141, 46, 341, 48, 44, 44, 44, 341, + 341, 46, 341, 44, 44, 44, 341, 341, 46, 48, + 341, 341, 341, 341, 341, 150, 151, 151, 151, 151, + 152, 48, 341, 341, 151, 151, 151, 151, 151, 48, + 341, 341, 44, 44, 44, 153, 48, 46, 341, 151, + 151, 151, 151, 151, 151, 44, 44, 44, 341, 154, + 46, 44, 44, 44, 341, 341, 46, 155, 44, 44, + 44, 341, 341, 46, 341, 48, 44, 44, 44, 341, + 341, 46, 44, 44, 44, 341, 341, 46, 48, 341, + + 341, 341, 156, 341, 48, 44, 44, 44, 341, 341, + 46, 48, 341, 44, 44, 44, 158, 157, 46, 48, + 341, 44, 44, 44, 341, 48, 46, 341, 159, 341, + 44, 44, 44, 341, 161, 46, 341, 160, 48, 44, + 44, 44, 341, 341, 46, 341, 48, 44, 44, 44, + 341, 341, 46, 164, 48, 341, 341, 162, 341, 341, + 163, 341, 341, 48, 341, 341, 166, 341, 44, 44, + 44, 165, 48, 46, 44, 44, 44, 341, 341, 46, + 48, 44, 44, 44, 341, 341, 46, 341, 44, 44, + 44, 167, 341, 46, 44, 44, 44, 341, 341, 46, + + 168, 48, 341, 341, 44, 44, 44, 48, 169, 46, + 44, 44, 44, 341, 48, 46, 341, 341, 341, 170, + 341, 48, 341, 341, 341, 341, 341, 48, 44, 44, + 44, 341, 341, 46, 341, 341, 341, 48, 171, 172, + 341, 341, 179, 48, 341, 177, 178, 178, 178, 178, + 180, 341, 341, 341, 178, 178, 178, 178, 178, 341, + 341, 48, 44, 44, 44, 341, 341, 46, 341, 178, + 178, 178, 178, 178, 178, 44, 44, 44, 341, 181, + 46, 44, 44, 44, 341, 341, 46, 44, 44, 44, + 183, 184, 46, 341, 341, 48, 44, 44, 44, 341, + + 341, 46, 341, 341, 182, 341, 187, 341, 48, 341, + 44, 44, 44, 341, 48, 46, 44, 44, 44, 341, + 48, 46, 341, 341, 185, 44, 44, 44, 341, 48, + 46, 44, 44, 44, 341, 341, 46, 341, 341, 186, + 44, 44, 44, 48, 341, 192, 188, 341, 341, 48, + 44, 44, 44, 341, 341, 46, 189, 341, 48, 341, + 44, 44, 44, 341, 48, 46, 341, 341, 341, 190, + 341, 191, 341, 48, 341, 44, 44, 44, 341, 341, + 46, 341, 341, 48, 44, 44, 44, 341, 341, 46, + 44, 44, 44, 48, 341, 46, 44, 44, 44, 341, + + 341, 46, 341, 341, 193, 341, 341, 194, 48, 44, + 44, 44, 341, 341, 199, 341, 341, 48, 341, 341, + 44, 44, 44, 48, 196, 200, 341, 341, 341, 48, + 201, 195, 44, 44, 44, 341, 198, 46, 44, 44, + 44, 197, 48, 46, 44, 44, 44, 341, 205, 209, + 341, 341, 341, 48, 44, 44, 44, 341, 341, 46, + 341, 341, 44, 44, 44, 48, 341, 46, 44, 44, + 44, 48, 341, 46, 341, 341, 341, 48, 341, 341, + 341, 204, 45, 45, 45, 45, 341, 48, 341, 341, + 45, 45, 45, 45, 45, 48, 341, 341, 44, 44, + + 44, 48, 206, 210, 341, 45, 45, 45, 45, 45, + 45, 207, 341, 341, 208, 44, 44, 44, 341, 341, + 211, 341, 44, 44, 44, 341, 341, 46, 44, 44, + 44, 48, 212, 46, 44, 44, 44, 341, 341, 46, + 44, 44, 44, 341, 341, 46, 341, 341, 48, 44, + 44, 44, 341, 341, 46, 48, 341, 44, 44, 44, + 341, 48, 46, 44, 44, 44, 341, 48, 46, 341, + 341, 213, 341, 48, 341, 341, 341, 341, 214, 44, + 44, 44, 48, 341, 46, 215, 341, 44, 44, 44, + 48, 216, 46, 44, 44, 44, 48, 341, 46, 44, + + 44, 44, 341, 341, 46, 341, 341, 341, 217, 341, + 219, 341, 48, 341, 218, 341, 44, 44, 44, 220, + 48, 46, 44, 44, 44, 341, 48, 46, 44, 44, + 44, 341, 48, 46, 341, 341, 221, 44, 44, 44, + 341, 341, 46, 223, 222, 44, 44, 44, 341, 48, + 46, 44, 44, 44, 341, 48, 46, 341, 341, 341, + 225, 48, 44, 44, 44, 341, 341, 46, 341, 224, + 48, 341, 341, 228, 227, 44, 44, 44, 48, 341, + 46, 44, 44, 44, 48, 341, 46, 44, 44, 44, + 341, 341, 46, 341, 341, 48, 341, 230, 229, 44, + + 44, 44, 231, 341, 46, 341, 341, 341, 48, 341, + 44, 44, 44, 341, 48, 46, 341, 44, 44, 44, + 48, 232, 238, 44, 44, 44, 341, 341, 46, 341, + 233, 341, 48, 44, 44, 44, 234, 341, 239, 44, + 44, 44, 341, 48, 46, 341, 44, 44, 44, 341, + 48, 46, 341, 44, 44, 44, 48, 235, 46, 341, + 341, 341, 236, 237, 341, 341, 48, 341, 240, 44, + 44, 44, 48, 341, 46, 44, 44, 44, 341, 48, + 46, 341, 44, 44, 44, 245, 48, 46, 44, 44, + 44, 341, 241, 46, 44, 44, 44, 242, 247, 46, + + 341, 243, 48, 341, 44, 44, 44, 341, 48, 249, + 341, 44, 44, 44, 341, 48, 46, 341, 44, 44, + 44, 48, 244, 46, 44, 44, 44, 48, 250, 46, + 341, 246, 341, 341, 44, 44, 44, 48, 341, 46, + 44, 44, 44, 341, 48, 46, 341, 341, 248, 341, + 341, 48, 341, 341, 44, 44, 44, 48, 341, 255, + 44, 44, 44, 341, 341, 256, 251, 48, 252, 44, + 44, 44, 341, 48, 257, 44, 44, 44, 341, 341, + 46, 341, 341, 44, 44, 44, 253, 48, 46, 341, + 341, 254, 341, 48, 44, 44, 44, 341, 341, 46, + + 341, 341, 48, 341, 44, 44, 44, 341, 48, 261, + 44, 44, 44, 341, 341, 46, 48, 44, 44, 44, + 341, 341, 46, 259, 258, 341, 341, 48, 341, 44, + 44, 44, 341, 260, 46, 341, 341, 48, 341, 44, + 44, 44, 341, 48, 46, 341, 44, 44, 44, 341, + 48, 46, 44, 44, 44, 341, 341, 46, 44, 44, + 44, 341, 48, 46, 341, 263, 341, 341, 262, 341, + 264, 341, 48, 341, 341, 266, 341, 265, 341, 48, + 341, 44, 44, 44, 341, 48, 46, 44, 44, 44, + 341, 48, 46, 341, 341, 44, 44, 44, 269, 267, + + 46, 44, 44, 44, 268, 341, 46, 341, 44, 44, + 44, 341, 341, 46, 48, 341, 341, 341, 270, 341, + 48, 44, 44, 44, 341, 341, 275, 341, 48, 341, + 44, 44, 44, 341, 48, 276, 341, 44, 44, 44, + 271, 48, 46, 341, 44, 44, 44, 341, 272, 46, + 341, 273, 341, 341, 48, 44, 44, 44, 341, 274, + 46, 341, 341, 48, 44, 44, 44, 341, 341, 46, + 48, 341, 341, 277, 44, 44, 44, 48, 341, 46, + 44, 44, 44, 341, 341, 46, 341, 341, 48, 44, + 44, 44, 341, 341, 46, 341, 341, 48, 44, 44, + + 44, 341, 278, 46, 341, 341, 280, 48, 279, 44, + 44, 44, 341, 48, 285, 341, 341, 281, 44, 44, + 44, 341, 48, 286, 341, 44, 44, 44, 341, 282, + 46, 48, 44, 44, 44, 283, 341, 46, 44, 44, + 44, 341, 48, 46, 341, 341, 341, 341, 341, 284, + 341, 48, 341, 341, 44, 44, 44, 341, 48, 46, + 341, 44, 44, 44, 341, 48, 46, 44, 44, 44, + 341, 48, 46, 341, 341, 44, 44, 44, 287, 341, + 46, 44, 44, 44, 288, 289, 46, 48, 44, 44, + 44, 341, 341, 295, 48, 341, 341, 44, 44, 44, + + 48, 291, 46, 341, 290, 341, 341, 292, 48, 341, + 341, 44, 44, 44, 48, 293, 46, 341, 341, 294, + 341, 48, 341, 44, 44, 44, 341, 341, 298, 341, + 48, 341, 341, 296, 44, 44, 44, 341, 341, 46, + 44, 44, 44, 341, 48, 46, 44, 44, 44, 341, + 341, 46, 44, 44, 44, 297, 48, 46, 44, 44, + 44, 341, 341, 46, 44, 44, 44, 48, 341, 46, + 341, 341, 341, 48, 299, 341, 341, 341, 341, 48, + 300, 44, 44, 44, 341, 48, 46, 44, 44, 44, + 341, 48, 46, 44, 44, 44, 341, 48, 307, 341, + + 302, 341, 341, 301, 341, 341, 303, 341, 341, 304, + 44, 44, 44, 341, 48, 308, 44, 44, 44, 341, + 48, 46, 44, 44, 44, 341, 48, 46, 44, 44, + 44, 341, 305, 46, 341, 341, 306, 44, 44, 44, + 341, 341, 46, 48, 341, 44, 44, 44, 341, 48, + 46, 44, 44, 44, 341, 48, 46, 44, 44, 44, + 341, 48, 315, 44, 44, 44, 341, 341, 316, 309, + 48, 44, 44, 44, 341, 310, 46, 312, 48, 341, + 341, 311, 341, 341, 48, 341, 44, 44, 44, 313, + 48, 46, 44, 44, 44, 341, 48, 46, 341, 314, + + 44, 44, 44, 341, 48, 46, 341, 44, 44, 44, + 341, 341, 46, 341, 341, 317, 44, 44, 44, 48, + 341, 46, 44, 44, 44, 48, 341, 46, 341, 44, + 44, 44, 319, 48, 324, 341, 44, 44, 44, 318, + 48, 46, 44, 44, 44, 321, 341, 326, 341, 48, + 341, 341, 320, 341, 341, 48, 44, 44, 44, 341, + 341, 327, 48, 341, 341, 44, 44, 44, 322, 48, + 46, 341, 325, 341, 323, 48, 44, 44, 44, 341, + 341, 46, 44, 44, 44, 341, 341, 46, 341, 48, + 44, 44, 44, 341, 341, 46, 341, 341, 48, 341, + + 44, 44, 44, 341, 341, 46, 44, 44, 44, 48, + 332, 46, 44, 44, 44, 48, 341, 335, 328, 341, + 329, 341, 341, 48, 341, 44, 44, 44, 341, 341, + 46, 330, 341, 48, 341, 44, 44, 44, 331, 48, + 46, 44, 44, 44, 341, 48, 46, 341, 44, 44, + 44, 341, 333, 46, 341, 341, 341, 334, 48, 44, + 44, 44, 341, 341, 340, 336, 341, 341, 48, 341, + 341, 337, 341, 341, 48, 341, 341, 341, 341, 341, + 341, 48, 341, 341, 341, 341, 341, 338, 341, 341, + 341, 341, 48, 341, 341, 339, 36, 36, 36, 36, + + 36, 45, 45, 45, 45, 45, 61, 341, 61, 61, + 61, 80, 341, 80, 341, 80, 82, 82, 82, 82, + 82, 86, 86, 86, 86, 86, 107, 341, 107, 107, + 107, 118, 118, 118, 11, 341, 341, 341, 341, 341, + 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, + 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, + 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, + 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, + 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, + 341, 341, 341, 341, 341, 341, 341 + } ; -static const flex_int16_t yy_chk[2031] = +static const flex_int16_t yy_chk[2298] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -1094,223 +1136,253 @@ static const flex_int16_t yy_chk[2031] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 3, 3, 3, 4, 4, 4, 3, 9, 7, - 4, 5, 5, 8, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 10, 13, 316, 13, 21, - 5, 5, 9, 5, 21, 315, 5, 25, 5, 25, - - 5, 26, 25, 25, 25, 25, 5, 5, 7, 10, - 5, 27, 8, 37, 5, 37, 26, 44, 17, 5, - 17, 17, 17, 17, 31, 5, 5, 15, 15, 15, - 28, 17, 15, 19, 27, 19, 19, 19, 19, 31, - 20, 20, 20, 20, 71, 44, 19, 17, 32, 33, - 15, 20, 42, 28, 42, 314, 45, 45, 45, 313, - 15, 45, 19, 193, 71, 15, 15, 20, 15, 73, - 15, 32, 33, 15, 15, 15, 15, 15, 72, 15, - 22, 15, 22, 22, 22, 22, 47, 47, 47, 45, - 48, 47, 73, 22, 49, 49, 49, 48, 72, 49, - - 74, 50, 50, 50, 169, 108, 50, 144, 116, 22, - 112, 85, 51, 51, 51, 50, 79, 51, 48, 47, - 74, 108, 48, 52, 52, 52, 48, 49, 52, 69, - 69, 69, 69, 48, 50, 47, 48, 78, 48, 48, - 76, 50, 81, 49, 50, 51, 53, 53, 53, 75, - 43, 53, 54, 54, 54, 41, 52, 54, 51, 39, - 55, 55, 55, 76, 106, 55, 56, 56, 56, 75, - 81, 56, 52, 57, 57, 57, 52, 107, 57, 53, - 109, 58, 58, 58, 110, 54, 58, 106, 54, 38, - 53, 111, 138, 55, 24, 53, 55, 107, 14, 56, - - 59, 59, 59, 109, 110, 59, 57, 111, 138, 57, - 70, 70, 70, 70, 58, 61, 61, 61, 61, 11, - 56, 58, 141, 0, 0, 0, 61, 0, 0, 0, - 58, 0, 62, 59, 62, 62, 62, 62, 141, 84, - 84, 84, 61, 0, 84, 62, 0, 0, 59, 63, - 0, 63, 59, 0, 63, 63, 63, 63, 0, 0, - 64, 62, 64, 64, 64, 64, 65, 65, 65, 65, - 0, 83, 84, 64, 0, 0, 0, 65, 83, 86, - 86, 86, 0, 0, 86, 0, 0, 84, 0, 64, - 0, 0, 0, 65, 0, 88, 88, 88, 0, 83, - - 88, 0, 0, 83, 89, 89, 89, 83, 0, 89, - 0, 0, 86, 0, 83, 0, 0, 83, 0, 83, - 83, 87, 87, 87, 87, 0, 0, 0, 88, 87, - 87, 87, 87, 87, 90, 90, 90, 89, 0, 90, - 0, 0, 88, 88, 87, 87, 87, 87, 87, 87, - 91, 91, 91, 0, 0, 91, 92, 92, 92, 0, - 0, 92, 0, 93, 93, 93, 0, 90, 93, 0, - 0, 90, 94, 94, 94, 0, 0, 94, 0, 0, - 95, 95, 95, 91, 0, 95, 0, 0, 91, 92, - 96, 96, 96, 0, 0, 96, 93, 97, 97, 97, - - 0, 0, 97, 0, 0, 94, 99, 99, 99, 0, - 92, 99, 93, 95, 98, 98, 98, 95, 0, 98, - 0, 0, 0, 96, 0, 94, 0, 0, 0, 0, - 97, 0, 96, 100, 100, 100, 0, 0, 100, 99, - 101, 101, 101, 0, 0, 101, 0, 98, 0, 102, - 102, 102, 0, 97, 102, 103, 103, 103, 0, 99, - 103, 98, 0, 104, 104, 104, 100, 0, 104, 115, - 115, 115, 0, 101, 115, 120, 120, 120, 0, 0, - 120, 0, 102, 0, 100, 0, 100, 102, 103, 0, - 0, 0, 0, 0, 0, 101, 104, 0, 0, 103, - - 0, 0, 115, 104, 0, 119, 119, 119, 120, 0, - 119, 122, 122, 122, 0, 0, 122, 0, 0, 0, - 0, 0, 115, 118, 118, 118, 118, 0, 120, 0, - 0, 118, 118, 118, 118, 118, 0, 0, 119, 0, - 123, 123, 123, 0, 122, 123, 118, 118, 118, 118, - 118, 118, 119, 124, 124, 124, 0, 0, 124, 125, - 125, 125, 0, 0, 125, 122, 126, 126, 126, 0, - 0, 126, 0, 123, 127, 127, 127, 0, 0, 127, - 128, 128, 128, 0, 0, 128, 124, 0, 0, 0, - 123, 0, 125, 129, 129, 129, 0, 0, 129, 126, - - 0, 130, 130, 130, 125, 124, 130, 127, 0, 131, - 131, 131, 0, 128, 131, 0, 126, 0, 132, 132, - 132, 0, 128, 132, 0, 127, 129, 133, 133, 133, - 0, 0, 133, 0, 130, 134, 134, 134, 0, 0, - 134, 130, 131, 0, 0, 129, 0, 0, 129, 0, - 0, 132, 0, 0, 132, 0, 135, 135, 135, 131, - 133, 135, 136, 136, 136, 0, 0, 136, 134, 137, - 137, 137, 0, 0, 137, 134, 146, 146, 146, 0, - 133, 146, 148, 148, 148, 0, 0, 148, 0, 135, - 0, 149, 149, 149, 0, 136, 149, 0, 0, 0, - - 0, 135, 137, 0, 0, 0, 0, 0, 0, 146, - 0, 0, 0, 0, 0, 148, 0, 0, 136, 0, - 137, 0, 148, 0, 149, 0, 0, 146, 147, 147, - 147, 147, 0, 0, 0, 0, 147, 147, 147, 147, - 147, 0, 149, 150, 150, 150, 0, 0, 150, 0, - 0, 147, 147, 147, 147, 147, 147, 151, 151, 151, - 0, 0, 151, 152, 152, 152, 0, 0, 152, 153, - 153, 153, 151, 151, 153, 0, 150, 154, 154, 154, - 0, 0, 154, 0, 0, 150, 0, 154, 0, 0, - 151, 0, 155, 155, 155, 0, 152, 155, 156, 156, - - 156, 0, 153, 156, 0, 0, 152, 157, 157, 157, - 154, 0, 157, 158, 158, 158, 0, 0, 158, 0, - 0, 153, 159, 159, 159, 155, 0, 159, 155, 0, - 0, 156, 160, 160, 160, 0, 0, 160, 156, 0, - 157, 0, 161, 161, 161, 0, 158, 161, 0, 0, - 0, 157, 0, 158, 0, 159, 0, 162, 162, 162, - 0, 0, 162, 0, 0, 160, 163, 163, 163, 0, - 0, 163, 164, 164, 164, 161, 0, 164, 165, 165, - 165, 0, 0, 165, 0, 0, 160, 0, 0, 161, - 162, 166, 166, 166, 0, 0, 166, 162, 0, 163, - - 0, 166, 171, 171, 171, 164, 0, 171, 173, 173, - 173, 165, 164, 173, 176, 176, 176, 163, 0, 176, - 0, 0, 0, 0, 166, 174, 174, 174, 0, 0, - 174, 0, 0, 0, 0, 171, 0, 175, 175, 175, - 0, 173, 175, 0, 0, 0, 0, 176, 0, 0, - 0, 171, 172, 172, 172, 172, 173, 0, 174, 0, - 172, 172, 172, 172, 172, 0, 177, 177, 177, 0, - 175, 177, 0, 0, 174, 172, 172, 172, 172, 172, - 172, 0, 0, 175, 178, 178, 178, 0, 0, 178, - 179, 179, 179, 0, 0, 179, 180, 180, 180, 177, - - 179, 180, 181, 181, 181, 0, 0, 181, 182, 182, - 182, 0, 0, 182, 183, 183, 183, 178, 0, 183, - 0, 0, 0, 179, 0, 184, 184, 184, 0, 180, - 184, 186, 186, 186, 0, 181, 186, 0, 0, 180, - 0, 182, 0, 0, 0, 0, 180, 183, 0, 187, - 187, 187, 0, 181, 187, 188, 188, 188, 184, 182, - 188, 189, 189, 189, 186, 0, 189, 0, 190, 190, - 190, 0, 183, 190, 0, 0, 184, 0, 192, 192, - 192, 0, 187, 192, 186, 195, 195, 195, 188, 187, - 195, 196, 196, 196, 189, 0, 196, 197, 197, 197, - - 0, 190, 197, 0, 0, 189, 188, 198, 198, 198, - 0, 192, 198, 0, 0, 0, 192, 0, 195, 0, - 0, 190, 0, 0, 196, 0, 0, 202, 202, 202, - 197, 195, 202, 203, 203, 203, 0, 0, 203, 0, - 198, 0, 0, 197, 196, 0, 0, 198, 204, 204, - 204, 0, 0, 204, 205, 205, 205, 0, 0, 205, - 202, 0, 206, 206, 206, 0, 203, 206, 0, 207, - 207, 207, 0, 202, 207, 208, 208, 208, 0, 0, - 208, 204, 203, 209, 209, 209, 0, 205, 209, 210, - 210, 210, 0, 0, 210, 206, 0, 204, 211, 211, - - 211, 0, 207, 211, 0, 212, 212, 212, 208, 207, - 212, 205, 0, 0, 206, 0, 209, 0, 209, 213, - 213, 213, 210, 0, 213, 0, 0, 0, 0, 213, - 0, 211, 214, 214, 214, 0, 0, 214, 212, 216, - 216, 216, 210, 0, 216, 0, 211, 0, 0, 216, - 0, 0, 213, 0, 217, 217, 217, 0, 212, 217, - 0, 218, 218, 218, 0, 214, 218, 0, 219, 219, - 219, 218, 216, 219, 220, 220, 220, 0, 0, 220, - 0, 214, 0, 221, 221, 221, 0, 217, 221, 0, - 0, 222, 222, 222, 218, 0, 222, 223, 223, 223, - - 0, 219, 223, 224, 224, 224, 0, 220, 224, 0, - 225, 225, 225, 0, 0, 225, 221, 0, 220, 0, - 228, 228, 228, 219, 222, 228, 229, 229, 229, 0, - 223, 229, 230, 230, 230, 221, 224, 230, 0, 231, - 231, 231, 222, 225, 231, 232, 232, 232, 0, 0, - 232, 0, 0, 228, 0, 233, 233, 233, 0, 229, - 233, 0, 236, 236, 236, 230, 229, 236, 0, 228, - 0, 0, 231, 0, 234, 234, 234, 0, 232, 234, - 237, 237, 237, 0, 0, 237, 0, 0, 233, 238, - 238, 238, 0, 232, 238, 236, 231, 0, 232, 239, - - 239, 239, 0, 233, 239, 0, 0, 234, 0, 0, - 234, 0, 0, 237, 236, 0, 240, 240, 240, 0, - 237, 240, 238, 244, 244, 244, 238, 0, 244, 245, - 245, 245, 239, 0, 245, 247, 247, 247, 0, 0, - 247, 248, 248, 248, 0, 0, 248, 0, 0, 240, - 0, 0, 239, 249, 249, 249, 244, 0, 249, 250, - 250, 250, 245, 0, 250, 251, 251, 251, 247, 240, - 251, 0, 0, 244, 248, 0, 0, 248, 0, 0, - 245, 0, 252, 252, 252, 0, 249, 252, 253, 253, - 253, 0, 250, 253, 254, 254, 254, 0, 251, 254, - - 255, 255, 255, 0, 0, 255, 0, 251, 0, 0, - 249, 0, 250, 0, 0, 252, 0, 256, 256, 256, - 0, 253, 256, 257, 257, 257, 0, 254, 257, 0, - 0, 252, 0, 255, 253, 258, 258, 258, 0, 0, - 258, 260, 260, 260, 0, 254, 260, 261, 261, 261, - 256, 0, 261, 262, 262, 262, 257, 0, 262, 263, - 263, 263, 0, 0, 263, 264, 264, 264, 258, 0, - 264, 0, 0, 0, 260, 0, 257, 265, 265, 265, - 261, 0, 265, 0, 0, 0, 262, 258, 260, 266, - 266, 266, 263, 262, 266, 0, 0, 261, 264, 263, - - 269, 269, 269, 264, 0, 269, 270, 270, 270, 0, - 265, 270, 271, 271, 271, 0, 0, 271, 272, 272, - 272, 0, 266, 272, 0, 266, 273, 273, 273, 0, - 0, 273, 0, 269, 0, 274, 274, 274, 0, 270, - 274, 275, 275, 275, 269, 271, 275, 0, 277, 277, - 277, 272, 271, 277, 0, 278, 278, 278, 272, 273, - 278, 280, 280, 280, 0, 0, 280, 0, 274, 0, - 281, 281, 281, 0, 275, 281, 0, 0, 0, 0, - 0, 277, 273, 274, 0, 0, 275, 0, 278, 0, - 282, 282, 282, 0, 280, 282, 283, 283, 283, 277, - - 0, 283, 0, 281, 278, 284, 284, 284, 0, 0, - 284, 285, 285, 285, 0, 0, 285, 286, 286, 286, - 0, 0, 286, 282, 0, 289, 289, 289, 0, 283, - 289, 290, 290, 290, 0, 0, 290, 0, 284, 0, - 0, 0, 0, 282, 285, 284, 291, 291, 291, 283, - 286, 291, 292, 292, 292, 285, 0, 292, 289, 0, - 0, 293, 293, 293, 290, 286, 293, 296, 296, 296, - 0, 0, 296, 297, 297, 297, 0, 0, 297, 291, - 0, 298, 298, 298, 0, 292, 298, 0, 299, 299, - 299, 0, 292, 299, 293, 0, 300, 300, 300, 291, - - 296, 300, 0, 0, 0, 0, 297, 0, 0, 0, - 0, 0, 0, 293, 298, 0, 0, 0, 0, 296, - 0, 299, 0, 0, 0, 297, 0, 0, 0, 300, - 305, 305, 305, 305, 305, 306, 306, 306, 306, 306, - 307, 0, 307, 307, 307, 308, 0, 308, 0, 308, - 309, 309, 309, 309, 309, 310, 310, 310, 310, 310, - 311, 0, 311, 311, 311, 312, 312, 312, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304, - 304, 304, 304, 304, 304, 304, 304, 304, 304, 304 + 1, 1, 3, 3, 3, 4, 4, 4, 3, 9, + 7, 4, 5, 5, 8, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 10, 13, 44, 13, + 21, 5, 5, 9, 5, 21, 353, 5, 25, 5, + + 25, 5, 26, 25, 25, 25, 25, 5, 5, 7, + 10, 5, 27, 8, 28, 5, 44, 26, 31, 17, + 5, 17, 17, 17, 17, 352, 72, 5, 5, 15, + 15, 15, 17, 31, 15, 27, 19, 28, 19, 19, + 19, 19, 20, 20, 20, 20, 72, 351, 17, 19, + 32, 33, 15, 20, 37, 42, 37, 42, 45, 45, + 45, 350, 15, 45, 48, 19, 15, 15, 15, 20, + 15, 48, 15, 32, 33, 15, 15, 15, 15, 15, + 202, 15, 22, 15, 22, 22, 22, 22, 47, 47, + 47, 45, 48, 47, 74, 22, 48, 49, 49, 49, + + 48, 175, 49, 50, 50, 50, 73, 48, 50, 75, + 48, 22, 48, 48, 51, 51, 51, 74, 77, 51, + 82, 47, 52, 52, 52, 148, 73, 52, 51, 75, + 49, 76, 118, 49, 110, 108, 50, 47, 53, 53, + 53, 77, 109, 53, 54, 54, 54, 51, 82, 54, + 110, 76, 50, 111, 51, 52, 113, 51, 108, 55, + 55, 55, 109, 112, 55, 56, 56, 56, 52, 142, + 56, 53, 113, 57, 57, 57, 111, 54, 57, 58, + 58, 58, 114, 112, 58, 142, 86, 53, 54, 145, + 80, 53, 55, 54, 79, 55, 43, 41, 56, 39, + + 38, 56, 59, 59, 59, 145, 57, 59, 60, 60, + 60, 24, 58, 60, 14, 58, 11, 62, 62, 62, + 62, 63, 0, 63, 63, 63, 63, 57, 62, 0, + 0, 64, 0, 64, 63, 59, 64, 64, 64, 64, + 0, 60, 59, 0, 62, 0, 66, 66, 66, 66, + 63, 59, 70, 70, 70, 70, 60, 66, 0, 65, + 60, 65, 65, 65, 65, 71, 71, 71, 71, 84, + 0, 0, 65, 66, 0, 0, 84, 85, 85, 85, + 0, 0, 85, 0, 0, 0, 0, 0, 65, 87, + 87, 87, 0, 0, 87, 0, 0, 84, 90, 90, + + 90, 84, 0, 90, 0, 84, 89, 89, 89, 0, + 85, 89, 84, 0, 0, 84, 0, 84, 84, 0, + 0, 0, 87, 0, 0, 85, 88, 88, 88, 88, + 0, 90, 0, 0, 88, 88, 88, 88, 88, 89, + 0, 0, 91, 91, 91, 90, 90, 91, 0, 88, + 88, 88, 88, 88, 88, 92, 92, 92, 89, 0, + 92, 93, 93, 93, 0, 0, 93, 94, 94, 94, + 0, 0, 94, 0, 0, 91, 95, 95, 95, 0, + 0, 95, 96, 96, 96, 0, 0, 96, 92, 0, + 0, 0, 92, 0, 93, 0, 97, 97, 97, 93, + + 94, 97, 0, 98, 98, 98, 0, 0, 98, 95, + 0, 99, 99, 99, 0, 96, 99, 100, 100, 100, + 0, 94, 100, 0, 0, 95, 101, 101, 101, 97, + 0, 101, 0, 97, 0, 96, 98, 102, 102, 102, + 0, 0, 102, 0, 99, 98, 0, 103, 103, 103, + 100, 0, 103, 104, 104, 104, 0, 0, 104, 101, + 105, 105, 105, 0, 100, 105, 0, 0, 99, 0, + 102, 0, 106, 106, 106, 0, 0, 106, 0, 101, + 103, 0, 117, 117, 117, 0, 104, 117, 102, 102, + 102, 104, 0, 105, 0, 0, 121, 121, 121, 0, + + 0, 121, 103, 0, 105, 106, 0, 0, 122, 122, + 122, 0, 106, 122, 0, 117, 123, 123, 123, 0, + 0, 123, 0, 125, 125, 125, 0, 0, 125, 121, + 0, 0, 0, 0, 0, 117, 120, 120, 120, 120, + 121, 122, 0, 0, 120, 120, 120, 120, 120, 123, + 0, 0, 126, 126, 126, 122, 125, 126, 0, 120, + 120, 120, 120, 120, 120, 127, 127, 127, 0, 123, + 127, 128, 128, 128, 0, 0, 128, 125, 129, 129, + 129, 0, 0, 129, 0, 126, 130, 130, 130, 0, + 0, 130, 131, 131, 131, 0, 0, 131, 127, 0, + + 0, 0, 126, 0, 128, 132, 132, 132, 0, 0, + 132, 129, 0, 133, 133, 133, 128, 127, 133, 130, + 0, 134, 134, 134, 0, 131, 134, 0, 129, 0, + 135, 135, 135, 0, 131, 135, 0, 130, 132, 136, + 136, 136, 0, 0, 136, 0, 133, 137, 137, 137, + 0, 0, 137, 133, 134, 0, 0, 132, 0, 0, + 132, 0, 0, 135, 0, 0, 135, 0, 138, 138, + 138, 134, 136, 138, 139, 139, 139, 0, 0, 139, + 137, 140, 140, 140, 0, 0, 140, 0, 141, 141, + 141, 136, 0, 141, 150, 150, 150, 0, 0, 150, + + 137, 138, 0, 0, 152, 152, 152, 139, 138, 152, + 153, 153, 153, 0, 140, 153, 0, 0, 0, 139, + 0, 141, 0, 0, 0, 0, 0, 150, 154, 154, + 154, 0, 0, 154, 0, 0, 0, 152, 140, 141, + 0, 0, 152, 153, 0, 150, 151, 151, 151, 151, + 153, 0, 0, 0, 151, 151, 151, 151, 151, 0, + 0, 154, 155, 155, 155, 0, 0, 155, 0, 151, + 151, 151, 151, 151, 151, 156, 156, 156, 0, 154, + 156, 157, 157, 157, 0, 0, 157, 158, 158, 158, + 156, 156, 158, 0, 0, 155, 159, 159, 159, 0, + + 0, 159, 0, 0, 155, 0, 159, 0, 156, 0, + 160, 160, 160, 0, 157, 160, 161, 161, 161, 0, + 158, 161, 0, 0, 157, 162, 162, 162, 0, 159, + 162, 163, 163, 163, 0, 0, 163, 0, 0, 158, + 164, 164, 164, 160, 0, 164, 160, 0, 0, 161, + 165, 165, 165, 0, 0, 165, 161, 0, 162, 0, + 166, 166, 166, 0, 163, 166, 0, 0, 0, 162, + 0, 163, 0, 164, 0, 167, 167, 167, 0, 0, + 167, 0, 0, 165, 168, 168, 168, 0, 0, 168, + 169, 169, 169, 166, 0, 169, 170, 170, 170, 0, + + 0, 170, 0, 0, 165, 0, 0, 166, 167, 171, + 171, 171, 0, 0, 171, 0, 0, 168, 0, 0, + 172, 172, 172, 169, 168, 172, 0, 0, 0, 170, + 172, 167, 177, 177, 177, 0, 170, 177, 179, 179, + 179, 169, 171, 179, 183, 183, 183, 0, 179, 183, + 0, 0, 0, 172, 180, 180, 180, 0, 0, 180, + 0, 0, 181, 181, 181, 177, 0, 181, 182, 182, + 182, 179, 0, 182, 0, 0, 0, 183, 0, 0, + 0, 177, 178, 178, 178, 178, 0, 180, 0, 0, + 178, 178, 178, 178, 178, 181, 0, 0, 184, 184, + + 184, 182, 180, 184, 0, 178, 178, 178, 178, 178, + 178, 181, 0, 0, 182, 185, 185, 185, 0, 0, + 185, 0, 186, 186, 186, 0, 0, 186, 187, 187, + 187, 184, 186, 187, 188, 188, 188, 0, 0, 188, + 189, 189, 189, 0, 0, 189, 0, 0, 185, 190, + 190, 190, 0, 0, 190, 186, 0, 193, 193, 193, + 0, 187, 193, 191, 191, 191, 0, 188, 191, 0, + 0, 187, 0, 189, 0, 0, 0, 0, 187, 194, + 194, 194, 190, 0, 194, 188, 0, 195, 195, 195, + 193, 189, 195, 196, 196, 196, 191, 0, 196, 197, + + 197, 197, 0, 0, 197, 0, 0, 0, 190, 0, + 193, 0, 194, 0, 191, 0, 198, 198, 198, 194, + 195, 198, 201, 201, 201, 0, 196, 201, 204, 204, + 204, 0, 197, 204, 0, 0, 195, 205, 205, 205, + 0, 0, 205, 197, 196, 206, 206, 206, 0, 198, + 206, 207, 207, 207, 0, 201, 207, 0, 0, 0, + 201, 204, 208, 208, 208, 0, 0, 208, 0, 198, + 205, 0, 0, 205, 204, 212, 212, 212, 206, 0, + 212, 213, 213, 213, 207, 0, 213, 214, 214, 214, + 0, 0, 214, 0, 0, 208, 0, 207, 206, 215, + + 215, 215, 208, 0, 215, 0, 0, 0, 212, 0, + 216, 216, 216, 0, 213, 216, 0, 218, 218, 218, + 214, 212, 218, 217, 217, 217, 0, 0, 217, 0, + 213, 0, 215, 219, 219, 219, 214, 0, 219, 220, + 220, 220, 0, 216, 220, 0, 221, 221, 221, 0, + 218, 221, 0, 222, 222, 222, 217, 215, 222, 0, + 0, 0, 216, 217, 0, 0, 219, 0, 219, 223, + 223, 223, 220, 0, 223, 224, 224, 224, 0, 221, + 224, 0, 225, 225, 225, 224, 222, 225, 227, 227, + 227, 0, 220, 227, 228, 228, 228, 221, 227, 228, + + 0, 222, 223, 0, 229, 229, 229, 0, 224, 229, + 0, 231, 231, 231, 0, 225, 231, 0, 230, 230, + 230, 227, 223, 230, 232, 232, 232, 228, 230, 232, + 0, 225, 0, 0, 233, 233, 233, 229, 0, 233, + 234, 234, 234, 0, 231, 234, 0, 0, 228, 0, + 0, 230, 0, 0, 235, 235, 235, 232, 0, 235, + 236, 236, 236, 0, 0, 236, 231, 233, 232, 237, + 237, 237, 0, 234, 237, 240, 240, 240, 0, 0, + 240, 0, 0, 241, 241, 241, 233, 235, 241, 0, + 0, 234, 0, 236, 242, 242, 242, 0, 0, 242, + + 0, 0, 237, 0, 243, 243, 243, 0, 240, 243, + 244, 244, 244, 0, 0, 244, 241, 245, 245, 245, + 0, 0, 245, 241, 240, 0, 0, 242, 0, 246, + 246, 246, 0, 242, 246, 0, 0, 243, 0, 247, + 247, 247, 0, 244, 247, 0, 248, 248, 248, 0, + 245, 248, 250, 250, 250, 0, 0, 250, 251, 251, + 251, 0, 246, 251, 0, 245, 0, 0, 244, 0, + 245, 0, 247, 0, 0, 247, 0, 246, 0, 248, + 0, 252, 252, 252, 0, 250, 252, 253, 253, 253, + 0, 251, 253, 0, 0, 254, 254, 254, 251, 248, + + 254, 258, 258, 258, 250, 0, 258, 0, 259, 259, + 259, 0, 0, 259, 252, 0, 0, 0, 252, 0, + 253, 260, 260, 260, 0, 0, 260, 0, 254, 0, + 262, 262, 262, 0, 258, 262, 0, 263, 263, 263, + 253, 259, 263, 0, 264, 264, 264, 0, 254, 264, + 0, 258, 0, 0, 260, 265, 265, 265, 0, 259, + 265, 0, 0, 262, 266, 266, 266, 0, 0, 266, + 263, 0, 0, 263, 267, 267, 267, 264, 0, 267, + 268, 268, 268, 0, 0, 268, 0, 0, 265, 269, + 269, 269, 0, 0, 269, 0, 0, 266, 270, 270, + + 270, 0, 264, 270, 0, 0, 266, 267, 265, 271, + 271, 271, 0, 268, 271, 0, 0, 267, 272, 272, + 272, 0, 269, 272, 0, 273, 273, 273, 0, 268, + 273, 270, 274, 274, 274, 269, 0, 274, 277, 277, + 277, 0, 271, 277, 0, 0, 0, 0, 0, 270, + 0, 272, 0, 0, 278, 278, 278, 0, 273, 278, + 0, 279, 279, 279, 0, 274, 279, 280, 280, 280, + 0, 277, 280, 0, 0, 281, 281, 281, 273, 0, + 281, 282, 282, 282, 274, 277, 282, 278, 283, 283, + 283, 0, 0, 283, 279, 0, 0, 284, 284, 284, + + 280, 279, 284, 0, 278, 0, 0, 280, 281, 0, + 0, 287, 287, 287, 282, 281, 287, 0, 0, 282, + 0, 283, 0, 288, 288, 288, 0, 0, 288, 0, + 284, 0, 0, 284, 289, 289, 289, 0, 0, 289, + 290, 290, 290, 0, 287, 290, 291, 291, 291, 0, + 0, 291, 292, 292, 292, 287, 288, 292, 293, 293, + 293, 0, 0, 293, 294, 294, 294, 289, 0, 294, + 0, 0, 0, 290, 289, 0, 0, 0, 0, 291, + 290, 296, 296, 296, 0, 292, 296, 297, 297, 297, + 0, 293, 297, 299, 299, 299, 0, 294, 299, 0, + + 292, 0, 0, 291, 0, 0, 293, 0, 0, 294, + 300, 300, 300, 0, 296, 300, 301, 301, 301, 0, + 297, 301, 302, 302, 302, 0, 299, 302, 303, 303, + 303, 0, 296, 303, 0, 0, 297, 304, 304, 304, + 0, 0, 304, 300, 0, 305, 305, 305, 0, 301, + 305, 306, 306, 306, 0, 302, 306, 309, 309, 309, + 0, 303, 309, 310, 310, 310, 0, 0, 310, 301, + 304, 311, 311, 311, 0, 302, 311, 304, 305, 0, + 0, 303, 0, 0, 306, 0, 312, 312, 312, 305, + 309, 312, 313, 313, 313, 0, 310, 313, 0, 306, + + 314, 314, 314, 0, 311, 314, 0, 317, 317, 317, + 0, 0, 317, 0, 0, 311, 318, 318, 318, 312, + 0, 318, 319, 319, 319, 313, 0, 319, 0, 320, + 320, 320, 313, 314, 320, 0, 321, 321, 321, 312, + 317, 321, 322, 322, 322, 317, 0, 322, 0, 318, + 0, 0, 314, 0, 0, 319, 323, 323, 323, 0, + 0, 323, 320, 0, 0, 325, 325, 325, 318, 321, + 325, 0, 321, 0, 319, 322, 328, 328, 328, 0, + 0, 328, 329, 329, 329, 0, 0, 329, 0, 323, + 330, 330, 330, 0, 0, 330, 0, 0, 325, 0, + + 331, 331, 331, 0, 0, 331, 332, 332, 332, 328, + 331, 332, 333, 333, 333, 329, 0, 333, 325, 0, + 328, 0, 0, 330, 0, 334, 334, 334, 0, 0, + 334, 329, 0, 331, 0, 336, 336, 336, 330, 332, + 336, 337, 337, 337, 0, 333, 337, 0, 338, 338, + 338, 0, 331, 338, 0, 0, 0, 332, 334, 339, + 339, 339, 0, 0, 339, 334, 0, 0, 336, 0, + 0, 336, 0, 0, 337, 0, 0, 0, 0, 0, + 0, 338, 0, 0, 0, 0, 0, 337, 0, 0, + 0, 0, 339, 0, 0, 338, 342, 342, 342, 342, + + 342, 343, 343, 343, 343, 343, 344, 0, 344, 344, + 344, 345, 0, 345, 0, 345, 346, 346, 346, 346, + 346, 347, 347, 347, 347, 347, 348, 0, 348, 348, + 348, 349, 349, 349, 341, 341, 341, 341, 341, 341, + 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, + 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, + 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, + 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, + 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, + 341, 341, 341, 341, 341, 341, 341 + } ; static yy_state_type yy_last_accepting_state; @@ -1319,14 +1391,14 @@ static char *yy_last_accepting_cpos; extern int yy_flex_debug; int yy_flex_debug = 1; -static const flex_int16_t yy_rule_linenum[55] = +static const flex_int16_t yy_rule_linenum[59] = { 0, 133, 135, 137, 142, 143, 148, 149, 150, 162, 165, - 170, 177, 186, 195, 204, 215, 226, 235, 244, 253, - 262, 271, 280, 289, 298, 307, 316, 325, 334, 343, - 352, 361, 370, 379, 388, 397, 406, 505, 510, 515, - 520, 521, 522, 523, 524, 525, 527, 545, 558, 563, - 567, 569, 571, 573 + 170, 177, 186, 195, 204, 213, 225, 237, 246, 255, + 264, 273, 282, 291, 300, 309, 318, 327, 336, 345, + 354, 363, 372, 381, 390, 399, 408, 417, 426, 435, + 444, 543, 548, 553, 558, 559, 560, 561, 562, 563, + 565, 583, 596, 601, 605, 607, 609, 611 } ; /* The intent behind this definition is that it'll catch @@ -1381,7 +1453,7 @@ using isc::agent::AgentParser; /* To avoid the call to exit... oops! */ #define YY_FATAL_ERROR(msg) isc::agent::ParserContext::fatal(msg) -#line 1384 "agent_lexer.cc" +#line 1456 "agent_lexer.cc" /* noyywrap disables automatic rewinding for the next file to parse. Since we always parse only a single string, there's no need to do any wraps. And using yywrap requires linking with -lfl, which provides the default yywrap @@ -1407,8 +1479,8 @@ using isc::agent::AgentParser; by moving it ahead by yyleng bytes. yyleng specifies the length of the currently matched token. */ #define YY_USER_ACTION driver.loc_.columns(yyleng); -#line 1410 "agent_lexer.cc" -#line 1411 "agent_lexer.cc" +#line 1482 "agent_lexer.cc" +#line 1483 "agent_lexer.cc" #define INITIAL 0 #define COMMENT 1 @@ -1722,7 +1794,7 @@ YY_DECL } -#line 1725 "agent_lexer.cc" +#line 1797 "agent_lexer.cc" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { @@ -1751,13 +1823,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 305 ) + if ( yy_current_state >= 342 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; ++yy_cp; } - while ( yy_current_state != 304 ); + while ( yy_current_state != 341 ); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); @@ -1776,13 +1848,13 @@ do_action: /* This label is used only to access EOF actions. */ { if ( yy_act == 0 ) fprintf( stderr, "--scanner backing up\n" ); - else if ( yy_act < 55 ) + else if ( yy_act < 59 ) fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n", (long)yy_rule_linenum[yy_act], yytext ); - else if ( yy_act == 55 ) + else if ( yy_act == 59 ) fprintf( stderr, "--accepting default rule (\"%s\")\n", yytext ); - else if ( yy_act == 56 ) + else if ( yy_act == 60 ) fprintf( stderr, "--(end of buffer or a NUL)\n" ); else fprintf( stderr, "--EOF (start condition %d)\n", YY_START ); @@ -1925,34 +1997,48 @@ YY_RULE_SETUP case 15: YY_RULE_SETUP #line 204 "agent_lexer.ll" +{ + switch(driver.ctx_) { + case ParserContext::AGENT: + return AgentParser::make_BASIC_AUTHENTICATION_REALM(driver.loc_); + default: + return AgentParser::make_STRING("basic-authentication-realm", driver.loc_); + } +} + YY_BREAK +case 16: +YY_RULE_SETUP +#line 213 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::AGENT: case ParserContext::SERVER: case ParserContext::LOGGERS: + case ParserContext::BASIC_AUTHENTICATIONS: return AgentParser::make_USER_CONTEXT(driver.loc_); default: return AgentParser::make_STRING("user-context", driver.loc_); } } YY_BREAK -case 16: +case 17: YY_RULE_SETUP -#line 215 "agent_lexer.ll" +#line 225 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::AGENT: case ParserContext::SERVER: case ParserContext::LOGGERS: + case ParserContext::BASIC_AUTHENTICATIONS: return AgentParser::make_COMMENT(driver.loc_); default: return AgentParser::make_STRING("comment", driver.loc_); } } YY_BREAK -case 17: +case 18: YY_RULE_SETUP -#line 226 "agent_lexer.ll" +#line 237 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::AGENT: @@ -1962,9 +2048,9 @@ YY_RULE_SETUP } } YY_BREAK -case 18: +case 19: YY_RULE_SETUP -#line 235 "agent_lexer.ll" +#line 246 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::CONTROL_SOCKETS: @@ -1974,9 +2060,9 @@ YY_RULE_SETUP } } YY_BREAK -case 19: +case 20: YY_RULE_SETUP -#line 244 "agent_lexer.ll" +#line 255 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::CONTROL_SOCKETS: @@ -1986,9 +2072,9 @@ YY_RULE_SETUP } } YY_BREAK -case 20: +case 21: YY_RULE_SETUP -#line 253 "agent_lexer.ll" +#line 264 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::CONTROL_SOCKETS: @@ -1998,9 +2084,9 @@ YY_RULE_SETUP } } YY_BREAK -case 21: +case 22: YY_RULE_SETUP -#line 262 "agent_lexer.ll" +#line 273 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::SERVER: @@ -2010,9 +2096,9 @@ YY_RULE_SETUP } } YY_BREAK -case 22: +case 23: YY_RULE_SETUP -#line 271 "agent_lexer.ll" +#line 282 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::SERVER: @@ -2022,9 +2108,9 @@ YY_RULE_SETUP } } YY_BREAK -case 23: +case 24: YY_RULE_SETUP -#line 280 "agent_lexer.ll" +#line 291 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::SOCKET_TYPE: @@ -2034,9 +2120,9 @@ YY_RULE_SETUP } } YY_BREAK -case 24: +case 25: YY_RULE_SETUP -#line 289 "agent_lexer.ll" +#line 300 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::AGENT: @@ -2046,9 +2132,9 @@ YY_RULE_SETUP } } YY_BREAK -case 25: +case 26: YY_RULE_SETUP -#line 298 "agent_lexer.ll" +#line 309 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::HOOKS_LIBRARIES: @@ -2058,9 +2144,9 @@ YY_RULE_SETUP } } YY_BREAK -case 26: +case 27: YY_RULE_SETUP -#line 307 "agent_lexer.ll" +#line 318 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::HOOKS_LIBRARIES: @@ -2070,9 +2156,9 @@ YY_RULE_SETUP } } YY_BREAK -case 27: +case 28: YY_RULE_SETUP -#line 316 "agent_lexer.ll" +#line 327 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::AGENT: @@ -2082,9 +2168,9 @@ YY_RULE_SETUP } } YY_BREAK -case 28: +case 29: YY_RULE_SETUP -#line 325 "agent_lexer.ll" +#line 336 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::LOGGERS: @@ -2094,9 +2180,9 @@ YY_RULE_SETUP } } YY_BREAK -case 29: +case 30: YY_RULE_SETUP -#line 334 "agent_lexer.ll" +#line 345 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::LOGGERS: @@ -2106,9 +2192,9 @@ YY_RULE_SETUP } } YY_BREAK -case 30: +case 31: YY_RULE_SETUP -#line 343 "agent_lexer.ll" +#line 354 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::OUTPUT_OPTIONS: @@ -2118,9 +2204,9 @@ YY_RULE_SETUP } } YY_BREAK -case 31: +case 32: YY_RULE_SETUP -#line 352 "agent_lexer.ll" +#line 363 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::OUTPUT_OPTIONS: @@ -2130,9 +2216,9 @@ YY_RULE_SETUP } } YY_BREAK -case 32: +case 33: YY_RULE_SETUP -#line 361 "agent_lexer.ll" +#line 372 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::OUTPUT_OPTIONS: @@ -2142,9 +2228,9 @@ YY_RULE_SETUP } } YY_BREAK -case 33: +case 34: YY_RULE_SETUP -#line 370 "agent_lexer.ll" +#line 381 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::OUTPUT_OPTIONS: @@ -2154,9 +2240,9 @@ YY_RULE_SETUP } } YY_BREAK -case 34: +case 35: YY_RULE_SETUP -#line 379 "agent_lexer.ll" +#line 390 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::OUTPUT_OPTIONS: @@ -2166,9 +2252,9 @@ YY_RULE_SETUP } } YY_BREAK -case 35: +case 36: YY_RULE_SETUP -#line 388 "agent_lexer.ll" +#line 399 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::LOGGERS: @@ -2178,9 +2264,9 @@ YY_RULE_SETUP } } YY_BREAK -case 36: +case 37: YY_RULE_SETUP -#line 397 "agent_lexer.ll" +#line 408 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::LOGGERS: @@ -2190,9 +2276,45 @@ YY_RULE_SETUP } } YY_BREAK -case 37: +case 38: YY_RULE_SETUP -#line 406 "agent_lexer.ll" +#line 417 "agent_lexer.ll" +{ + switch(driver.ctx_) { + case ParserContext::AGENT: + return AgentParser::make_BASIC_AUTHENTICATIONS(driver.loc_); + default: + return AgentParser::make_STRING("basic-authentications", driver.loc_); + } +} + YY_BREAK +case 39: +YY_RULE_SETUP +#line 426 "agent_lexer.ll" +{ + switch(driver.ctx_) { + case ParserContext::BASIC_AUTHENTICATIONS: + return AgentParser::make_USER(driver.loc_); + default: + return AgentParser::make_STRING("user", driver.loc_); + } +} + YY_BREAK +case 40: +YY_RULE_SETUP +#line 435 "agent_lexer.ll" +{ + switch(driver.ctx_) { + case ParserContext::BASIC_AUTHENTICATIONS: + return AgentParser::make_PASSWORD(driver.loc_); + default: + return AgentParser::make_STRING("password", driver.loc_); + } +} + YY_BREAK +case 41: +YY_RULE_SETUP +#line 444 "agent_lexer.ll" { /* A string has been matched. It contains the actual string and single quotes. We need to get those quotes out of the way and just use its content, e.g. @@ -2292,65 +2414,65 @@ YY_RULE_SETUP return AgentParser::make_STRING(decoded, driver.loc_); } YY_BREAK -case 38: -/* rule 38 can match eol */ +case 42: +/* rule 42 can match eol */ YY_RULE_SETUP -#line 505 "agent_lexer.ll" +#line 543 "agent_lexer.ll" { /* Bad string with a forbidden control character inside */ driver.error(driver.loc_, "Invalid control in " + std::string(yytext)); } YY_BREAK -case 39: -/* rule 39 can match eol */ +case 43: +/* rule 43 can match eol */ YY_RULE_SETUP -#line 510 "agent_lexer.ll" +#line 548 "agent_lexer.ll" { /* Bad string with a bad escape inside */ driver.error(driver.loc_, "Bad escape in " + std::string(yytext)); } YY_BREAK -case 40: +case 44: YY_RULE_SETUP -#line 515 "agent_lexer.ll" +#line 553 "agent_lexer.ll" { /* Bad string with an open escape at the end */ driver.error(driver.loc_, "Overflow escape in " + std::string(yytext)); } YY_BREAK -case 41: +case 45: YY_RULE_SETUP -#line 520 "agent_lexer.ll" +#line 558 "agent_lexer.ll" { return AgentParser::make_LSQUARE_BRACKET(driver.loc_); } YY_BREAK -case 42: +case 46: YY_RULE_SETUP -#line 521 "agent_lexer.ll" +#line 559 "agent_lexer.ll" { return AgentParser::make_RSQUARE_BRACKET(driver.loc_); } YY_BREAK -case 43: +case 47: YY_RULE_SETUP -#line 522 "agent_lexer.ll" +#line 560 "agent_lexer.ll" { return AgentParser::make_LCURLY_BRACKET(driver.loc_); } YY_BREAK -case 44: +case 48: YY_RULE_SETUP -#line 523 "agent_lexer.ll" +#line 561 "agent_lexer.ll" { return AgentParser::make_RCURLY_BRACKET(driver.loc_); } YY_BREAK -case 45: +case 49: YY_RULE_SETUP -#line 524 "agent_lexer.ll" +#line 562 "agent_lexer.ll" { return AgentParser::make_COMMA(driver.loc_); } YY_BREAK -case 46: +case 50: YY_RULE_SETUP -#line 525 "agent_lexer.ll" +#line 563 "agent_lexer.ll" { return AgentParser::make_COLON(driver.loc_); } YY_BREAK -case 47: +case 51: YY_RULE_SETUP -#line 527 "agent_lexer.ll" +#line 565 "agent_lexer.ll" { /* An integer was found. */ std::string tmp(yytext); @@ -2369,9 +2491,9 @@ YY_RULE_SETUP return AgentParser::make_INTEGER(integer, driver.loc_); } YY_BREAK -case 48: +case 52: YY_RULE_SETUP -#line 545 "agent_lexer.ll" +#line 583 "agent_lexer.ll" { /* A floating point was found. */ std::string tmp(yytext); @@ -2385,43 +2507,43 @@ YY_RULE_SETUP return AgentParser::make_FLOAT(fp, driver.loc_); } YY_BREAK -case 49: +case 53: YY_RULE_SETUP -#line 558 "agent_lexer.ll" +#line 596 "agent_lexer.ll" { string tmp(yytext); return AgentParser::make_BOOLEAN(tmp == "true", driver.loc_); } YY_BREAK -case 50: +case 54: YY_RULE_SETUP -#line 563 "agent_lexer.ll" +#line 601 "agent_lexer.ll" { return AgentParser::make_NULL_TYPE(driver.loc_); } YY_BREAK -case 51: +case 55: YY_RULE_SETUP -#line 567 "agent_lexer.ll" +#line 605 "agent_lexer.ll" driver.error (driver.loc_, "JSON true reserved keyword is lower case only"); YY_BREAK -case 52: +case 56: YY_RULE_SETUP -#line 569 "agent_lexer.ll" +#line 607 "agent_lexer.ll" driver.error (driver.loc_, "JSON false reserved keyword is lower case only"); YY_BREAK -case 53: +case 57: YY_RULE_SETUP -#line 571 "agent_lexer.ll" +#line 609 "agent_lexer.ll" driver.error (driver.loc_, "JSON null reserved keyword is lower case only"); YY_BREAK -case 54: +case 58: YY_RULE_SETUP -#line 573 "agent_lexer.ll" +#line 611 "agent_lexer.ll" driver.error (driver.loc_, "Invalid character: " + std::string(yytext)); YY_BREAK case YY_STATE_EOF(INITIAL): -#line 575 "agent_lexer.ll" +#line 613 "agent_lexer.ll" { if (driver.states_.empty()) { return AgentParser::make_END(driver.loc_); @@ -2445,12 +2567,12 @@ case YY_STATE_EOF(INITIAL): BEGIN(DIR_EXIT); } YY_BREAK -case 55: +case 59: YY_RULE_SETUP -#line 598 "agent_lexer.ll" +#line 636 "agent_lexer.ll" ECHO; YY_BREAK -#line 2453 "agent_lexer.cc" +#line 2575 "agent_lexer.cc" case YY_END_OF_BUFFER: { @@ -2769,7 +2891,7 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 305 ) + if ( yy_current_state >= 342 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; @@ -2802,11 +2924,11 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 305 ) + if ( yy_current_state >= 342 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; - yy_is_jam = (yy_current_state == 304); + yy_is_jam = (yy_current_state == 341); return yy_is_jam ? 0 : yy_current_state; } @@ -3555,7 +3677,7 @@ void yyfree (void * ptr ) /* %ok-for-header */ -#line 598 "agent_lexer.ll" +#line 636 "agent_lexer.ll" using namespace isc::dhcp; diff --git a/src/bin/agent/agent_parser.cc b/src/bin/agent/agent_parser.cc index 9bd835ec6e..1f26b881e4 100644 --- a/src/bin/agent/agent_parser.cc +++ b/src/bin/agent/agent_parser.cc @@ -1,4 +1,4 @@ -// A Bison parser, made by GNU Bison 3.7.1. +// A Bison parser, made by GNU Bison 3.6.4. // Skeleton implementation for Bison LALR(1) parsers in C++ @@ -209,25 +209,25 @@ namespace isc { namespace agent { { switch (that.kind ()) { - case symbol_kind::S_value: // value - case symbol_kind::S_map_value: // map_value - case symbol_kind::S_socket_type_value: // socket_type_value + case 54: // value + case 57: // map_value + case 110: // socket_type_value value.YY_MOVE_OR_COPY< ElementPtr > (YY_MOVE (that.value)); break; - case symbol_kind::S_BOOLEAN: // "boolean" + case 45: // "boolean" value.YY_MOVE_OR_COPY< bool > (YY_MOVE (that.value)); break; - case symbol_kind::S_FLOAT: // "floating point" + case 44: // "floating point" value.YY_MOVE_OR_COPY< double > (YY_MOVE (that.value)); break; - case symbol_kind::S_INTEGER: // "integer" + case 43: // "integer" value.YY_MOVE_OR_COPY< int64_t > (YY_MOVE (that.value)); break; - case symbol_kind::S_STRING: // "constant string" + case 42: // "constant string" value.YY_MOVE_OR_COPY< std::string > (YY_MOVE (that.value)); break; @@ -246,25 +246,25 @@ namespace isc { namespace agent { { switch (that.kind ()) { - case symbol_kind::S_value: // value - case symbol_kind::S_map_value: // map_value - case symbol_kind::S_socket_type_value: // socket_type_value + case 54: // value + case 57: // map_value + case 110: // socket_type_value value.move< ElementPtr > (YY_MOVE (that.value)); break; - case symbol_kind::S_BOOLEAN: // "boolean" + case 45: // "boolean" value.move< bool > (YY_MOVE (that.value)); break; - case symbol_kind::S_FLOAT: // "floating point" + case 44: // "floating point" value.move< double > (YY_MOVE (that.value)); break; - case symbol_kind::S_INTEGER: // "integer" + case 43: // "integer" value.move< int64_t > (YY_MOVE (that.value)); break; - case symbol_kind::S_STRING: // "constant string" + case 42: // "constant string" value.move< std::string > (YY_MOVE (that.value)); break; @@ -283,25 +283,25 @@ namespace isc { namespace agent { state = that.state; switch (that.kind ()) { - case symbol_kind::S_value: // value - case symbol_kind::S_map_value: // map_value - case symbol_kind::S_socket_type_value: // socket_type_value + case 54: // value + case 57: // map_value + case 110: // socket_type_value value.copy< ElementPtr > (that.value); break; - case symbol_kind::S_BOOLEAN: // "boolean" + case 45: // "boolean" value.copy< bool > (that.value); break; - case symbol_kind::S_FLOAT: // "floating point" + case 44: // "floating point" value.copy< double > (that.value); break; - case symbol_kind::S_INTEGER: // "integer" + case 43: // "integer" value.copy< int64_t > (that.value); break; - case symbol_kind::S_STRING: // "constant string" + case 42: // "constant string" value.copy< std::string > (that.value); break; @@ -319,25 +319,25 @@ namespace isc { namespace agent { state = that.state; switch (that.kind ()) { - case symbol_kind::S_value: // value - case symbol_kind::S_map_value: // map_value - case symbol_kind::S_socket_type_value: // socket_type_value + case 54: // value + case 57: // map_value + case 110: // socket_type_value value.move< ElementPtr > (that.value); break; - case symbol_kind::S_BOOLEAN: // "boolean" + case 45: // "boolean" value.move< bool > (that.value); break; - case symbol_kind::S_FLOAT: // "floating point" + case 44: // "floating point" value.move< double > (that.value); break; - case symbol_kind::S_INTEGER: // "integer" + case 43: // "integer" value.move< int64_t > (that.value); break; - case symbol_kind::S_STRING: // "constant string" + case 42: // "constant string" value.move< std::string > (that.value); break; @@ -377,44 +377,44 @@ namespace isc { namespace agent { << yysym.location << ": "; switch (yykind) { - case symbol_kind::S_STRING: // "constant string" -#line 99 "agent_parser.yy" + case 42: // "constant string" +#line 104 "agent_parser.yy" { yyoutput << yysym.value.template as < std::string > (); } #line 384 "agent_parser.cc" break; - case symbol_kind::S_INTEGER: // "integer" -#line 99 "agent_parser.yy" + case 43: // "integer" +#line 104 "agent_parser.yy" { yyoutput << yysym.value.template as < int64_t > (); } #line 390 "agent_parser.cc" break; - case symbol_kind::S_FLOAT: // "floating point" -#line 99 "agent_parser.yy" + case 44: // "floating point" +#line 104 "agent_parser.yy" { yyoutput << yysym.value.template as < double > (); } #line 396 "agent_parser.cc" break; - case symbol_kind::S_BOOLEAN: // "boolean" -#line 99 "agent_parser.yy" + case 45: // "boolean" +#line 104 "agent_parser.yy" { yyoutput << yysym.value.template as < bool > (); } #line 402 "agent_parser.cc" break; - case symbol_kind::S_value: // value -#line 99 "agent_parser.yy" + case 54: // value +#line 104 "agent_parser.yy" { yyoutput << yysym.value.template as < ElementPtr > (); } #line 408 "agent_parser.cc" break; - case symbol_kind::S_map_value: // map_value -#line 99 "agent_parser.yy" + case 57: // map_value +#line 104 "agent_parser.yy" { yyoutput << yysym.value.template as < ElementPtr > (); } #line 414 "agent_parser.cc" break; - case symbol_kind::S_socket_type_value: // socket_type_value -#line 99 "agent_parser.yy" + case 110: // socket_type_value +#line 104 "agent_parser.yy" { yyoutput << yysym.value.template as < ElementPtr > (); } #line 420 "agent_parser.cc" break; @@ -646,25 +646,25 @@ namespace isc { namespace agent { when using variants. */ switch (yyr1_[yyn]) { - case symbol_kind::S_value: // value - case symbol_kind::S_map_value: // map_value - case symbol_kind::S_socket_type_value: // socket_type_value + case 54: // value + case 57: // map_value + case 110: // socket_type_value yylhs.value.emplace< ElementPtr > (); break; - case symbol_kind::S_BOOLEAN: // "boolean" + case 45: // "boolean" yylhs.value.emplace< bool > (); break; - case symbol_kind::S_FLOAT: // "floating point" + case 44: // "floating point" yylhs.value.emplace< double > (); break; - case symbol_kind::S_INTEGER: // "integer" + case 43: // "integer" yylhs.value.emplace< int64_t > (); break; - case symbol_kind::S_STRING: // "constant string" + case 42: // "constant string" yylhs.value.emplace< std::string > (); break; @@ -688,26 +688,26 @@ namespace isc { namespace agent { { switch (yyn) { - case 2: // $@1: %empty -#line 110 "agent_parser.yy" + case 2: +#line 115 "agent_parser.yy" { ctx.ctx_ = ctx.NO_KEYWORDS; } #line 695 "agent_parser.cc" break; - case 4: // $@2: %empty -#line 111 "agent_parser.yy" + case 4: +#line 116 "agent_parser.yy" { ctx.ctx_ = ctx.CONFIG; } #line 701 "agent_parser.cc" break; - case 6: // $@3: %empty -#line 112 "agent_parser.yy" + case 6: +#line 117 "agent_parser.yy" { ctx.ctx_ = ctx.AGENT; } #line 707 "agent_parser.cc" break; - case 8: // $@4: %empty -#line 120 "agent_parser.yy" + case 8: +#line 125 "agent_parser.yy" { // Parse the Control-agent map ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location))); @@ -716,16 +716,16 @@ namespace isc { namespace agent { #line 717 "agent_parser.cc" break; - case 9: // sub_agent: "{" $@4 global_params "}" -#line 124 "agent_parser.yy" + case 9: +#line 129 "agent_parser.yy" { // parsing completed } #line 725 "agent_parser.cc" break; - case 10: // json: value -#line 131 "agent_parser.yy" + case 10: +#line 136 "agent_parser.yy" { // Push back the JSON value on the stack ctx.stack_.push_back(yystack_[0].value.as < ElementPtr > ()); @@ -733,50 +733,50 @@ namespace isc { namespace agent { #line 734 "agent_parser.cc" break; - case 11: // value: "integer" -#line 137 "agent_parser.yy" + case 11: +#line 142 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ElementPtr(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location))); } #line 740 "agent_parser.cc" break; - case 12: // value: "floating point" -#line 138 "agent_parser.yy" + case 12: +#line 143 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ElementPtr(new DoubleElement(yystack_[0].value.as < double > (), ctx.loc2pos(yystack_[0].location))); } #line 746 "agent_parser.cc" break; - case 13: // value: "boolean" -#line 139 "agent_parser.yy" + case 13: +#line 144 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ElementPtr(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location))); } #line 752 "agent_parser.cc" break; - case 14: // value: "constant string" -#line 140 "agent_parser.yy" + case 14: +#line 145 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); } #line 758 "agent_parser.cc" break; - case 15: // value: "null" -#line 141 "agent_parser.yy" + case 15: +#line 146 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ElementPtr(new NullElement(ctx.loc2pos(yystack_[0].location))); } #line 764 "agent_parser.cc" break; - case 16: // value: map -#line 142 "agent_parser.yy" + case 16: +#line 147 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ctx.stack_.back(); ctx.stack_.pop_back(); } #line 770 "agent_parser.cc" break; - case 17: // value: list_generic -#line 143 "agent_parser.yy" + case 17: +#line 148 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ctx.stack_.back(); ctx.stack_.pop_back(); } #line 776 "agent_parser.cc" break; - case 18: // $@5: %empty -#line 147 "agent_parser.yy" + case 18: +#line 152 "agent_parser.yy" { // This code is executed when we're about to start parsing // the content of the map @@ -786,8 +786,8 @@ namespace isc { namespace agent { #line 787 "agent_parser.cc" break; - case 19: // map: "{" $@5 map_content "}" -#line 152 "agent_parser.yy" + case 19: +#line 157 "agent_parser.yy" { // map parsing completed. If we ever want to do any wrap up // (maybe some sanity checking), this would be the best place @@ -796,14 +796,14 @@ namespace isc { namespace agent { #line 797 "agent_parser.cc" break; - case 20: // map_value: map -#line 158 "agent_parser.yy" + case 20: +#line 163 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ctx.stack_.back(); ctx.stack_.pop_back(); } #line 803 "agent_parser.cc" break; - case 23: // not_empty_map: "constant string" ":" value -#line 172 "agent_parser.yy" + case 23: +#line 177 "agent_parser.yy" { // map containing a single entry ctx.stack_.back()->set(yystack_[2].value.as < std::string > (), yystack_[0].value.as < ElementPtr > ()); @@ -811,8 +811,8 @@ namespace isc { namespace agent { #line 812 "agent_parser.cc" break; - case 24: // not_empty_map: not_empty_map "," "constant string" ":" value -#line 176 "agent_parser.yy" + case 24: +#line 181 "agent_parser.yy" { // map consisting of a shorter map followed by // comma and string:value @@ -821,8 +821,8 @@ namespace isc { namespace agent { #line 822 "agent_parser.cc" break; - case 25: // $@6: %empty -#line 183 "agent_parser.yy" + case 25: +#line 188 "agent_parser.yy" { ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.push_back(l); @@ -830,15 +830,15 @@ namespace isc { namespace agent { #line 831 "agent_parser.cc" break; - case 26: // list_generic: "[" $@6 list_content "]" -#line 186 "agent_parser.yy" + case 26: +#line 191 "agent_parser.yy" { } #line 838 "agent_parser.cc" break; - case 29: // not_empty_list: value -#line 193 "agent_parser.yy" + case 29: +#line 198 "agent_parser.yy" { // List consisting of a single element. ctx.stack_.back()->add(yystack_[0].value.as < ElementPtr > ()); @@ -846,8 +846,8 @@ namespace isc { namespace agent { #line 847 "agent_parser.cc" break; - case 30: // not_empty_list: not_empty_list "," value -#line 197 "agent_parser.yy" + case 30: +#line 202 "agent_parser.yy" { // List ending with , and a value. ctx.stack_.back()->add(yystack_[0].value.as < ElementPtr > ()); @@ -855,8 +855,8 @@ namespace isc { namespace agent { #line 856 "agent_parser.cc" break; - case 31: // unknown_map_entry: "constant string" ":" -#line 210 "agent_parser.yy" + case 31: +#line 215 "agent_parser.yy" { const std::string& where = ctx.contextName(); const std::string& keyword = yystack_[1].value.as < std::string > (); @@ -866,8 +866,8 @@ namespace isc { namespace agent { #line 867 "agent_parser.cc" break; - case 32: // $@7: %empty -#line 218 "agent_parser.yy" + case 32: +#line 223 "agent_parser.yy" { // This code is executed when we're about to start parsing // the content of the map @@ -877,8 +877,8 @@ namespace isc { namespace agent { #line 878 "agent_parser.cc" break; - case 33: // agent_syntax_map: "{" $@7 global_objects "}" -#line 223 "agent_parser.yy" + case 33: +#line 228 "agent_parser.yy" { // map parsing completed. If we ever want to do any wrap up // (maybe some sanity checking), this would be the best place @@ -887,8 +887,8 @@ namespace isc { namespace agent { #line 888 "agent_parser.cc" break; - case 36: // $@8: %empty -#line 238 "agent_parser.yy" + case 36: +#line 243 "agent_parser.yy" { // Let's create a MapElement that will represent it, add it to the @@ -903,8 +903,8 @@ namespace isc { namespace agent { #line 904 "agent_parser.cc" break; - case 37: // agent_object: "Control-agent" $@8 ":" "{" global_params "}" -#line 248 "agent_parser.yy" + case 37: +#line 253 "agent_parser.yy" { // Ok, we're done with parsing control-agent. Let's take the map // off the stack. @@ -914,16 +914,16 @@ namespace isc { namespace agent { #line 915 "agent_parser.cc" break; - case 48: // $@9: %empty -#line 271 "agent_parser.yy" + case 50: +#line 278 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } #line 923 "agent_parser.cc" break; - case 49: // http_host: "http-host" $@9 ":" "constant string" -#line 273 "agent_parser.yy" + case 51: +#line 280 "agent_parser.yy" { ElementPtr host(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("http-host", host); @@ -932,8 +932,8 @@ namespace isc { namespace agent { #line 933 "agent_parser.cc" break; - case 50: // http_port: "http-port" ":" "integer" -#line 279 "agent_parser.yy" + case 52: +#line 286 "agent_parser.yy" { ElementPtr prf(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("http-port", prf); @@ -941,16 +941,34 @@ namespace isc { namespace agent { #line 942 "agent_parser.cc" break; - case 51: // $@10: %empty -#line 284 "agent_parser.yy" - { + case 53: +#line 291 "agent_parser.yy" + { ctx.enter(ctx.NO_KEYWORDS); } #line 950 "agent_parser.cc" break; - case 52: // user_context: "user-context" $@10 ":" map_value -#line 286 "agent_parser.yy" + case 54: +#line 293 "agent_parser.yy" + { + ElementPtr realm(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); + ctx.stack_.back()->set("basic-authentication-realm", realm); + ctx.leave(); +} +#line 960 "agent_parser.cc" + break; + + case 55: +#line 299 "agent_parser.yy" + { + ctx.enter(ctx.NO_KEYWORDS); +} +#line 968 "agent_parser.cc" + break; + + case 56: +#line 301 "agent_parser.yy" { ElementPtr parent = ctx.stack_.back(); ElementPtr user_context = yystack_[0].value.as < ElementPtr > (); @@ -973,19 +991,19 @@ namespace isc { namespace agent { parent->set("user-context", user_context); ctx.leave(); } -#line 977 "agent_parser.cc" +#line 995 "agent_parser.cc" break; - case 53: // $@11: %empty -#line 309 "agent_parser.yy" + case 57: +#line 324 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } -#line 985 "agent_parser.cc" +#line 1003 "agent_parser.cc" break; - case 54: // comment: "comment" $@11 ":" "constant string" -#line 311 "agent_parser.yy" + case 58: +#line 326 "agent_parser.yy" { ElementPtr parent = ctx.stack_.back(); ElementPtr user_context(new MapElement(ctx.loc2pos(yystack_[3].location))); @@ -1010,389 +1028,463 @@ namespace isc { namespace agent { parent->set("user-context", user_context); ctx.leave(); } -#line 1014 "agent_parser.cc" +#line 1032 "agent_parser.cc" break; - case 55: // $@12: %empty -#line 337 "agent_parser.yy" + case 59: +#line 352 "agent_parser.yy" { ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("hooks-libraries", l); ctx.stack_.push_back(l); ctx.enter(ctx.HOOKS_LIBRARIES); } -#line 1025 "agent_parser.cc" +#line 1043 "agent_parser.cc" break; - case 56: // hooks_libraries: "hooks-libraries" $@12 ":" "[" hooks_libraries_list "]" -#line 342 "agent_parser.yy" + case 60: +#line 357 "agent_parser.yy" { ctx.stack_.pop_back(); ctx.leave(); } -#line 1034 "agent_parser.cc" +#line 1052 "agent_parser.cc" break; - case 61: // $@13: %empty -#line 355 "agent_parser.yy" + case 65: +#line 370 "agent_parser.yy" { ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->add(m); ctx.stack_.push_back(m); } -#line 1044 "agent_parser.cc" +#line 1062 "agent_parser.cc" break; - case 62: // hooks_library: "{" $@13 hooks_params "}" -#line 359 "agent_parser.yy" + case 66: +#line 374 "agent_parser.yy" { ctx.stack_.pop_back(); } -#line 1052 "agent_parser.cc" +#line 1070 "agent_parser.cc" break; - case 68: // $@14: %empty -#line 372 "agent_parser.yy" + case 72: +#line 387 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } -#line 1060 "agent_parser.cc" +#line 1078 "agent_parser.cc" break; - case 69: // library: "library" $@14 ":" "constant string" -#line 374 "agent_parser.yy" + case 73: +#line 389 "agent_parser.yy" { ElementPtr lib(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("library", lib); ctx.leave(); } -#line 1070 "agent_parser.cc" +#line 1088 "agent_parser.cc" break; - case 70: // $@15: %empty -#line 380 "agent_parser.yy" + case 74: +#line 395 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } -#line 1078 "agent_parser.cc" +#line 1096 "agent_parser.cc" break; - case 71: // parameters: "parameters" $@15 ":" map_value -#line 382 "agent_parser.yy" - { + case 75: +#line 397 "agent_parser.yy" + { ctx.stack_.back()->set("parameters", yystack_[0].value.as < ElementPtr > ()); ctx.leave(); } -#line 1087 "agent_parser.cc" +#line 1105 "agent_parser.cc" break; - case 72: // $@16: %empty -#line 390 "agent_parser.yy" + case 76: +#line 405 "agent_parser.yy" { ElementPtr m(new MapElement(ctx.loc2pos(yystack_[2].location))); ctx.stack_.back()->set("control-sockets", m); ctx.stack_.push_back(m); ctx.enter(ctx.CONTROL_SOCKETS); } -#line 1098 "agent_parser.cc" +#line 1116 "agent_parser.cc" break; - case 73: // control_sockets: "control-sockets" ":" "{" $@16 control_sockets_params "}" -#line 395 "agent_parser.yy" + case 77: +#line 410 "agent_parser.yy" { ctx.stack_.pop_back(); ctx.leave(); } -#line 1107 "agent_parser.cc" +#line 1125 "agent_parser.cc" break; - case 80: // $@17: %empty -#line 416 "agent_parser.yy" + case 84: +#line 431 "agent_parser.yy" { ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("dhcp4", m); ctx.stack_.push_back(m); ctx.enter(ctx.SERVER); } -#line 1118 "agent_parser.cc" +#line 1136 "agent_parser.cc" break; - case 81: // dhcp4_server_socket: "dhcp4" $@17 ":" "{" control_socket_params "}" -#line 421 "agent_parser.yy" + case 85: +#line 436 "agent_parser.yy" { ctx.stack_.pop_back(); ctx.leave(); } -#line 1127 "agent_parser.cc" +#line 1145 "agent_parser.cc" break; - case 82: // $@18: %empty -#line 427 "agent_parser.yy" + case 86: +#line 442 "agent_parser.yy" { ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("dhcp6", m); ctx.stack_.push_back(m); ctx.enter(ctx.SERVER); } -#line 1138 "agent_parser.cc" +#line 1156 "agent_parser.cc" break; - case 83: // dhcp6_server_socket: "dhcp6" $@18 ":" "{" control_socket_params "}" -#line 432 "agent_parser.yy" + case 87: +#line 447 "agent_parser.yy" { ctx.stack_.pop_back(); ctx.leave(); } -#line 1147 "agent_parser.cc" +#line 1165 "agent_parser.cc" break; - case 84: // $@19: %empty -#line 438 "agent_parser.yy" + case 88: +#line 453 "agent_parser.yy" { ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("d2", m); ctx.stack_.push_back(m); ctx.enter(ctx.SERVER); } -#line 1158 "agent_parser.cc" +#line 1176 "agent_parser.cc" break; - case 85: // d2_server_socket: "d2" $@19 ":" "{" control_socket_params "}" -#line 443 "agent_parser.yy" + case 89: +#line 458 "agent_parser.yy" { ctx.stack_.pop_back(); ctx.leave(); } -#line 1167 "agent_parser.cc" +#line 1185 "agent_parser.cc" break; - case 93: // $@20: %empty -#line 462 "agent_parser.yy" + case 97: +#line 477 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } -#line 1175 "agent_parser.cc" +#line 1193 "agent_parser.cc" break; - case 94: // socket_name: "socket-name" $@20 ":" "constant string" -#line 464 "agent_parser.yy" + case 98: +#line 479 "agent_parser.yy" { ElementPtr name(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("socket-name", name); ctx.leave(); } -#line 1185 "agent_parser.cc" +#line 1203 "agent_parser.cc" break; - case 95: // $@21: %empty -#line 471 "agent_parser.yy" + case 99: +#line 486 "agent_parser.yy" { ctx.enter(ctx.SOCKET_TYPE); } -#line 1193 "agent_parser.cc" +#line 1211 "agent_parser.cc" break; - case 96: // socket_type: "socket-type" $@21 ":" socket_type_value -#line 473 "agent_parser.yy" + case 100: +#line 488 "agent_parser.yy" { ctx.stack_.back()->set("socket-type", yystack_[0].value.as < ElementPtr > ()); ctx.leave(); } -#line 1202 "agent_parser.cc" +#line 1220 "agent_parser.cc" break; - case 97: // socket_type_value: "unix" -#line 479 "agent_parser.yy" + case 101: +#line 494 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement("unix", ctx.loc2pos(yystack_[0].location))); } -#line 1208 "agent_parser.cc" +#line 1226 "agent_parser.cc" break; - case 98: // $@22: %empty -#line 486 "agent_parser.yy" + case 102: +#line 501 "agent_parser.yy" + { + ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location))); + ctx.stack_.back()->set("basic-authentications", l); + ctx.stack_.push_back(l); + ctx.enter(ctx.BASIC_AUTHENTICATIONS); +} +#line 1237 "agent_parser.cc" + break; + + case 103: +#line 506 "agent_parser.yy" + { + ctx.stack_.pop_back(); + ctx.leave(); +} +#line 1246 "agent_parser.cc" + break; + + case 108: +#line 519 "agent_parser.yy" + { + ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location))); + ctx.stack_.back()->add(m); + ctx.stack_.push_back(m); +} +#line 1256 "agent_parser.cc" + break; + + case 109: +#line 523 "agent_parser.yy" + { + ctx.stack_.pop_back(); +} +#line 1264 "agent_parser.cc" + break; + + case 117: +#line 538 "agent_parser.yy" + { + ctx.enter(ctx.NO_KEYWORDS); +} +#line 1272 "agent_parser.cc" + break; + + case 118: +#line 540 "agent_parser.yy" + { + ElementPtr user(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); + ctx.stack_.back()->set("user", user); + ctx.leave(); +} +#line 1282 "agent_parser.cc" + break; + + case 119: +#line 546 "agent_parser.yy" + { + ctx.enter(ctx.NO_KEYWORDS); +} +#line 1290 "agent_parser.cc" + break; + + case 120: +#line 548 "agent_parser.yy" + { + ElementPtr password(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); + ctx.stack_.back()->set("password", password); + ctx.leave(); +} +#line 1300 "agent_parser.cc" + break; + + case 121: +#line 558 "agent_parser.yy" { ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("loggers", l); ctx.stack_.push_back(l); ctx.enter(ctx.LOGGERS); } -#line 1219 "agent_parser.cc" +#line 1311 "agent_parser.cc" break; - case 99: // loggers: "loggers" $@22 ":" "[" loggers_entries "]" -#line 491 "agent_parser.yy" + case 122: +#line 563 "agent_parser.yy" { ctx.stack_.pop_back(); ctx.leave(); } -#line 1228 "agent_parser.cc" +#line 1320 "agent_parser.cc" break; - case 102: // $@23: %empty -#line 503 "agent_parser.yy" + case 125: +#line 575 "agent_parser.yy" { ElementPtr l(new MapElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->add(l); ctx.stack_.push_back(l); } -#line 1238 "agent_parser.cc" +#line 1330 "agent_parser.cc" break; - case 103: // logger_entry: "{" $@23 logger_params "}" -#line 507 "agent_parser.yy" + case 126: +#line 579 "agent_parser.yy" { ctx.stack_.pop_back(); } -#line 1246 "agent_parser.cc" +#line 1338 "agent_parser.cc" break; - case 113: // $@24: %empty -#line 524 "agent_parser.yy" + case 136: +#line 596 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } -#line 1254 "agent_parser.cc" +#line 1346 "agent_parser.cc" break; - case 114: // name: "name" $@24 ":" "constant string" -#line 526 "agent_parser.yy" + case 137: +#line 598 "agent_parser.yy" { ElementPtr name(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("name", name); ctx.leave(); } -#line 1264 "agent_parser.cc" +#line 1356 "agent_parser.cc" break; - case 115: // debuglevel: "debuglevel" ":" "integer" -#line 532 "agent_parser.yy" + case 138: +#line 604 "agent_parser.yy" { ElementPtr dl(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("debuglevel", dl); } -#line 1273 "agent_parser.cc" +#line 1365 "agent_parser.cc" break; - case 116: // $@25: %empty -#line 537 "agent_parser.yy" + case 139: +#line 609 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } -#line 1281 "agent_parser.cc" +#line 1373 "agent_parser.cc" break; - case 117: // severity: "severity" $@25 ":" "constant string" -#line 539 "agent_parser.yy" + case 140: +#line 611 "agent_parser.yy" { ElementPtr sev(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("severity", sev); ctx.leave(); } -#line 1291 "agent_parser.cc" +#line 1383 "agent_parser.cc" break; - case 118: // $@26: %empty -#line 545 "agent_parser.yy" + case 141: +#line 617 "agent_parser.yy" { ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("output_options", l); ctx.stack_.push_back(l); ctx.enter(ctx.OUTPUT_OPTIONS); } -#line 1302 "agent_parser.cc" +#line 1394 "agent_parser.cc" break; - case 119: // output_options_list: "output_options" $@26 ":" "[" output_options_list_content "]" -#line 550 "agent_parser.yy" + case 142: +#line 622 "agent_parser.yy" { ctx.stack_.pop_back(); ctx.leave(); } -#line 1311 "agent_parser.cc" +#line 1403 "agent_parser.cc" break; - case 122: // $@27: %empty -#line 559 "agent_parser.yy" + case 145: +#line 631 "agent_parser.yy" { ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->add(m); ctx.stack_.push_back(m); } -#line 1321 "agent_parser.cc" +#line 1413 "agent_parser.cc" break; - case 123: // output_entry: "{" $@27 output_params_list "}" -#line 563 "agent_parser.yy" + case 146: +#line 635 "agent_parser.yy" { ctx.stack_.pop_back(); } -#line 1329 "agent_parser.cc" +#line 1421 "agent_parser.cc" break; - case 131: // $@28: %empty -#line 578 "agent_parser.yy" + case 154: +#line 650 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } -#line 1337 "agent_parser.cc" +#line 1429 "agent_parser.cc" break; - case 132: // output: "output" $@28 ":" "constant string" -#line 580 "agent_parser.yy" + case 155: +#line 652 "agent_parser.yy" { ElementPtr sev(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("output", sev); ctx.leave(); } -#line 1347 "agent_parser.cc" +#line 1439 "agent_parser.cc" break; - case 133: // flush: "flush" ":" "boolean" -#line 586 "agent_parser.yy" + case 156: +#line 658 "agent_parser.yy" { ElementPtr flush(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("flush", flush); } -#line 1356 "agent_parser.cc" +#line 1448 "agent_parser.cc" break; - case 134: // maxsize: "maxsize" ":" "integer" -#line 591 "agent_parser.yy" + case 157: +#line 663 "agent_parser.yy" { ElementPtr maxsize(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("maxsize", maxsize); } -#line 1365 "agent_parser.cc" +#line 1457 "agent_parser.cc" break; - case 135: // maxver: "maxver" ":" "integer" -#line 596 "agent_parser.yy" + case 158: +#line 668 "agent_parser.yy" { ElementPtr maxver(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("maxver", maxver); } -#line 1374 "agent_parser.cc" +#line 1466 "agent_parser.cc" break; - case 136: // $@29: %empty -#line 601 "agent_parser.yy" + case 159: +#line 673 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } -#line 1382 "agent_parser.cc" +#line 1474 "agent_parser.cc" break; - case 137: // pattern: "pattern" $@29 ":" "constant string" -#line 603 "agent_parser.yy" + case 160: +#line 675 "agent_parser.yy" { ElementPtr sev(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("pattern", sev); ctx.leave(); } -#line 1392 "agent_parser.cc" +#line 1484 "agent_parser.cc" break; -#line 1396 "agent_parser.cc" +#line 1488 "agent_parser.cc" default: break; @@ -1741,37 +1833,40 @@ namespace isc { namespace agent { } - const short AgentParser::yypact_ninf_ = -128; + const signed char AgentParser::yypact_ninf_ = -103; const signed char AgentParser::yytable_ninf_ = -1; const short AgentParser::yypact_[] = { - 65, -128, -128, -128, 7, 1, -2, 8, -128, -128, - -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, - -128, -128, -128, -128, 1, -6, 52, 5, -128, 44, - 70, 80, 75, 87, -128, 84, -128, -128, -128, 89, - -128, -128, 93, -128, -128, 94, -128, 6, -128, -128, - -128, -128, -128, -128, -128, -128, -128, 1, 1, -128, - 66, 99, -128, 101, 67, 103, 104, 102, 106, 107, - -128, 5, -128, -128, -128, 108, 109, 76, -128, 110, - 77, -128, 113, 114, -128, 1, 5, -128, -128, -128, - -128, -5, 115, 116, -128, 18, -128, -128, -128, -128, - 28, -128, -128, -128, -128, -128, 118, 117, -128, -128, - 45, -128, -128, 121, 122, 123, -5, -128, 11, -128, - 115, 40, 116, -128, 124, 125, 126, -128, -128, -128, - -128, 60, -128, -128, -128, -128, -128, -128, 133, -128, - -128, -128, -128, 68, -128, -128, -128, -128, -128, -128, - 9, 9, 9, 134, 135, 64, -128, 136, 137, 74, - 138, 40, -128, -128, -128, -128, -128, -128, 69, -128, - -128, -128, 71, 72, 83, 110, -128, 90, 139, -128, - 91, -128, 141, 142, 9, -128, -128, -128, -128, -128, - -128, 140, -128, 92, 127, -128, -128, 79, -128, -128, - -128, -128, 24, 140, -128, -128, 145, 146, 147, -128, - 78, -128, -128, -128, -128, -128, -128, -128, 148, 112, - 119, 120, 150, 24, -128, 105, -128, -128, -128, 128, - -128, -128, -128 + 56, -103, -103, -103, 8, 2, -5, 3, -103, -103, + -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, + -103, -103, -103, -103, 2, -14, 42, 1, -103, 44, + 51, 60, 62, 97, -103, 93, -103, -103, -103, 98, + -103, -103, -103, 99, -103, -103, -103, 101, -103, 57, + -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, + -103, 2, 2, -103, 65, 104, -103, 109, 71, 111, + 114, 115, 113, 117, 118, 119, -103, 1, -103, -103, + -103, 120, 121, 85, -103, 87, 123, 89, -103, 127, + 128, 129, -103, 2, 1, -103, -103, -103, -103, -103, + 40, 130, 131, 132, -103, 59, -103, -103, -103, -103, + 63, -103, -103, -103, -103, -103, 134, 122, -103, -103, + 135, 133, -103, -103, 15, -103, -103, 138, 139, 140, + 40, -103, 11, -103, 130, 21, -103, 131, -11, 132, + -103, 141, 142, 143, -103, -103, -103, -103, -103, -103, + 80, -103, -103, -103, -103, -103, -103, -103, 81, -103, + -103, -103, -103, -103, -103, 147, -103, -103, -103, -103, + 82, -103, -103, -103, -103, -103, -103, 19, 19, 19, + 148, 149, 11, -103, 150, 151, 14, -103, 153, 154, + 92, 155, -11, -103, -103, -103, -103, -103, -103, 83, + -103, -103, -103, 84, 90, 103, 105, -103, 125, 2, + -103, 126, 157, -103, 136, -103, 159, 160, 19, -103, + -103, -103, -103, -103, -103, -103, -103, 158, -103, 137, + 124, -103, -103, 26, -103, -103, -103, -103, 43, 158, + -103, -103, 165, 168, 169, -103, 91, -103, -103, -103, + -103, -103, -103, -103, 170, 144, 145, 152, 171, 43, + -103, 156, -103, -103, -103, 161, -103, -103, -103 }; const unsigned char @@ -1780,147 +1875,168 @@ namespace isc { namespace agent { 0, 2, 4, 6, 0, 0, 0, 0, 1, 25, 18, 15, 14, 11, 12, 13, 3, 10, 16, 17, 32, 5, 8, 7, 27, 21, 0, 0, 29, 0, - 28, 0, 0, 22, 36, 0, 34, 35, 48, 0, - 51, 53, 0, 55, 98, 0, 47, 0, 38, 40, - 41, 45, 46, 43, 42, 44, 26, 0, 0, 19, - 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, - 31, 0, 9, 30, 23, 0, 0, 0, 50, 0, - 0, 72, 0, 0, 39, 0, 0, 49, 20, 52, - 54, 0, 57, 0, 24, 0, 80, 82, 84, 79, - 0, 74, 76, 77, 78, 61, 0, 58, 59, 102, - 0, 100, 37, 0, 0, 0, 0, 73, 0, 56, - 0, 0, 0, 99, 0, 0, 0, 75, 68, 70, - 65, 0, 63, 66, 67, 60, 113, 118, 0, 116, - 112, 110, 111, 0, 104, 106, 108, 109, 107, 101, - 0, 0, 0, 0, 0, 0, 62, 0, 0, 0, - 0, 0, 103, 93, 95, 92, 90, 91, 0, 86, - 88, 89, 0, 0, 0, 0, 64, 0, 0, 115, - 0, 105, 0, 0, 0, 81, 83, 85, 69, 71, - 114, 0, 117, 0, 0, 87, 122, 0, 120, 94, - 97, 96, 0, 0, 119, 131, 0, 0, 0, 136, - 0, 124, 126, 127, 128, 129, 130, 121, 0, 0, - 0, 0, 0, 0, 123, 0, 133, 134, 135, 0, - 125, 132, 137 + 28, 0, 0, 22, 36, 0, 34, 35, 50, 0, + 53, 55, 57, 0, 102, 59, 121, 0, 49, 0, + 38, 40, 41, 42, 47, 48, 45, 43, 44, 46, + 26, 0, 0, 19, 0, 0, 33, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 31, 0, 9, 30, + 23, 0, 0, 0, 52, 0, 0, 0, 76, 0, + 0, 0, 39, 0, 0, 51, 54, 20, 56, 58, + 0, 104, 61, 0, 24, 0, 84, 86, 88, 83, + 0, 78, 80, 81, 82, 108, 0, 105, 106, 65, + 0, 62, 63, 125, 0, 123, 37, 0, 0, 0, + 0, 77, 0, 103, 0, 0, 60, 0, 0, 0, + 122, 0, 0, 0, 79, 117, 119, 116, 114, 115, + 0, 110, 112, 113, 107, 72, 74, 69, 0, 67, + 70, 71, 64, 136, 141, 0, 139, 135, 133, 134, + 0, 127, 129, 131, 132, 130, 124, 0, 0, 0, + 0, 0, 0, 109, 0, 0, 0, 66, 0, 0, + 0, 0, 0, 126, 97, 99, 96, 94, 95, 0, + 90, 92, 93, 0, 0, 0, 0, 111, 0, 0, + 68, 0, 0, 138, 0, 128, 0, 0, 0, 85, + 87, 89, 118, 120, 73, 75, 137, 0, 140, 0, + 0, 91, 145, 0, 143, 98, 101, 100, 0, 0, + 142, 154, 0, 0, 0, 159, 0, 147, 149, 150, + 151, 152, 153, 144, 0, 0, 0, 0, 0, 0, + 146, 0, 156, 157, 158, 0, 148, 155, 160 }; - const short + const signed char AgentParser::yypgoto_[] = { - -128, -128, -128, -128, -128, -128, -128, -128, -20, -76, - -128, -19, -128, -128, -128, -128, -128, -128, -27, -128, - -128, -128, -128, -128, -128, 81, 86, -128, -128, -128, - -26, -128, -25, -128, -128, -128, -128, -128, 35, -128, - -128, 10, -128, -128, -128, -128, -128, -128, -128, 46, - -128, -128, -128, -128, -128, -128, -127, -24, -128, -128, - -128, -128, -128, -128, -128, -128, 39, -128, -128, 2, - -128, -128, -128, -128, -128, -128, -128, -128, -39, -128, - -128, -55, -128, -128, -128, -128, -128, -128, -128 + -103, -103, -103, -103, -103, -103, -103, -103, -24, 94, + -103, -103, -103, -103, -103, -103, -103, -103, -26, -103, + -103, -103, -103, -103, -103, 32, 100, -103, -103, -103, + -103, -103, -22, -103, -21, -103, -103, -103, -103, -103, + 39, -103, -103, -4, -103, -103, -103, -103, -103, -103, + -103, 53, -103, -103, -103, -103, -103, -103, -102, -37, + -103, -103, -103, -103, -103, -103, -103, -103, -103, 50, + -103, -103, 4, -103, -103, -103, -103, -103, -103, -103, + 48, -103, -103, -2, -103, -103, -103, -103, -103, -103, + -103, -103, -48, -103, -103, -67, -103, -103, -103, -103, + -103, -103, -103 }; const short AgentParser::yydefgoto_[] = { -1, 4, 5, 6, 7, 23, 27, 16, 17, 18, - 25, 89, 32, 33, 19, 24, 29, 30, 165, 21, - 26, 35, 36, 37, 61, 47, 48, 49, 63, 50, - 166, 65, 167, 66, 53, 68, 106, 107, 108, 118, - 131, 132, 133, 153, 134, 154, 54, 91, 100, 101, - 102, 113, 103, 114, 104, 115, 168, 169, 170, 182, - 171, 183, 201, 55, 69, 110, 111, 121, 143, 144, - 145, 157, 146, 147, 160, 148, 158, 197, 198, 202, - 210, 211, 212, 218, 213, 214, 215, 216, 222 + 25, 98, 32, 33, 19, 24, 29, 30, 196, 21, + 26, 35, 36, 37, 65, 49, 50, 51, 67, 52, + 53, 69, 197, 70, 198, 71, 56, 74, 120, 121, + 122, 135, 158, 159, 160, 184, 161, 185, 57, 100, + 110, 111, 112, 127, 113, 128, 114, 129, 199, 200, + 201, 216, 202, 217, 237, 58, 73, 116, 117, 118, + 132, 150, 151, 152, 180, 153, 181, 59, 75, 124, + 125, 138, 170, 171, 172, 188, 173, 174, 191, 175, + 189, 233, 234, 238, 246, 247, 248, 254, 249, 250, + 251, 252, 258 }; - const unsigned char + const short AgentParser::yytable_[] = { - 46, 51, 52, 88, 28, 20, 9, 8, 10, 71, - 11, 96, 97, 98, 72, 22, 38, 39, 40, 41, - 42, 71, 40, 41, 172, 173, 112, 43, 163, 164, - 44, 116, 31, 45, 128, 129, 117, 73, 74, 12, - 13, 14, 15, 45, 46, 51, 52, 45, 122, 45, - 56, 123, 205, 40, 41, 206, 207, 208, 209, 46, - 51, 52, 34, 155, 99, 94, 136, 137, 156, 138, - 139, 161, 184, 57, 184, 184, 162, 185, 45, 186, - 187, 223, 203, 59, 58, 204, 224, 128, 129, 99, - 60, 130, 62, 64, 140, 141, 142, 67, 70, 88, - 1, 2, 3, 76, 75, 77, 78, 79, 80, 81, - 82, 83, 85, 179, 87, 90, 86, 10, 92, 93, - 120, 188, 105, 109, 119, 124, 125, 126, 190, 192, - 199, 150, 151, 152, 140, 141, 142, 159, 174, 175, - 177, 178, 180, 231, 191, 193, 194, 196, 200, 219, - 220, 221, 225, 226, 229, 135, 189, 84, 227, 228, - 195, 149, 127, 181, 217, 176, 232, 95, 230 + 28, 48, 20, 41, 42, 54, 55, 9, 8, 10, + 22, 11, 38, 39, 40, 41, 42, 43, 139, 163, + 164, 140, 165, 166, 44, 41, 42, 45, 31, 239, + 46, 47, 240, 41, 42, 145, 146, 79, 80, 194, + 195, 155, 156, 47, 12, 13, 14, 15, 155, 156, + 60, 48, 34, 47, 61, 54, 55, 106, 107, 108, + 77, 47, 77, 47, 62, 78, 130, 126, 48, 104, + 63, 131, 54, 55, 109, 241, 203, 204, 242, 243, + 244, 245, 47, 182, 186, 192, 218, 218, 183, 187, + 193, 219, 220, 218, 259, 1, 2, 3, 221, 260, + 64, 66, 68, 72, 109, 76, 147, 81, 82, 157, + 148, 149, 167, 83, 84, 85, 168, 169, 86, 87, + 88, 89, 90, 91, 93, 134, 105, 95, 94, 96, + 10, 99, 101, 102, 103, 213, 137, 115, 119, 123, + 133, 136, 141, 142, 143, 222, 236, 223, 177, 178, + 179, 190, 205, 206, 208, 209, 147, 211, 212, 214, + 148, 149, 227, 229, 230, 232, 167, 224, 226, 255, + 168, 169, 256, 257, 261, 265, 162, 92, 228, 235, + 97, 231, 210, 144, 154, 225, 207, 176, 263, 262, + 215, 253, 266, 0, 0, 264, 0, 0, 267, 0, + 0, 0, 0, 268 }; - const unsigned char + const short AgentParser::yycheck_[] = { - 27, 27, 27, 79, 24, 7, 5, 0, 7, 3, - 9, 16, 17, 18, 8, 7, 11, 12, 13, 14, - 15, 3, 13, 14, 151, 152, 8, 22, 19, 20, - 25, 3, 38, 38, 23, 24, 8, 57, 58, 38, - 39, 40, 41, 38, 71, 71, 71, 38, 3, 38, - 6, 6, 28, 13, 14, 31, 32, 33, 34, 86, - 86, 86, 10, 3, 91, 85, 26, 27, 8, 29, - 30, 3, 3, 3, 3, 3, 8, 8, 38, 8, - 8, 3, 3, 8, 4, 6, 8, 23, 24, 116, - 3, 118, 8, 4, 121, 121, 121, 4, 4, 175, - 35, 36, 37, 4, 38, 4, 39, 4, 4, 7, - 4, 4, 4, 39, 38, 38, 7, 7, 5, 5, - 3, 38, 7, 7, 6, 4, 4, 4, 38, 38, - 38, 7, 7, 7, 161, 161, 161, 4, 4, 4, - 4, 4, 4, 38, 5, 4, 4, 7, 21, 4, - 4, 4, 4, 41, 4, 120, 175, 71, 39, 39, - 184, 122, 116, 161, 203, 155, 38, 86, 223 + 24, 27, 7, 14, 15, 27, 27, 5, 0, 7, + 7, 9, 11, 12, 13, 14, 15, 16, 3, 30, + 31, 6, 33, 34, 23, 14, 15, 26, 42, 3, + 29, 42, 6, 14, 15, 24, 25, 61, 62, 20, + 21, 27, 28, 42, 42, 43, 44, 45, 27, 28, + 6, 77, 10, 42, 3, 77, 77, 17, 18, 19, + 3, 42, 3, 42, 4, 8, 3, 8, 94, 93, + 8, 8, 94, 94, 100, 32, 178, 179, 35, 36, + 37, 38, 42, 3, 3, 3, 3, 3, 8, 8, + 8, 8, 8, 3, 3, 39, 40, 41, 8, 8, + 3, 8, 4, 4, 130, 4, 132, 42, 4, 135, + 132, 132, 138, 4, 43, 4, 138, 138, 4, 4, + 7, 4, 4, 4, 4, 3, 94, 42, 7, 42, + 7, 42, 5, 5, 5, 43, 3, 7, 7, 7, + 6, 6, 4, 4, 4, 42, 22, 42, 7, 7, + 7, 4, 4, 4, 4, 4, 182, 4, 4, 4, + 182, 182, 5, 4, 4, 7, 192, 42, 42, 4, + 192, 192, 4, 4, 4, 4, 137, 77, 42, 42, + 86, 218, 186, 130, 134, 209, 182, 139, 43, 45, + 192, 239, 259, -1, -1, 43, -1, -1, 42, -1, + -1, -1, -1, 42 }; const unsigned char AgentParser::yystos_[] = { - 0, 35, 36, 37, 43, 44, 45, 46, 0, 5, - 7, 9, 38, 39, 40, 41, 49, 50, 51, 56, - 7, 61, 7, 47, 57, 52, 62, 48, 50, 58, - 59, 38, 54, 55, 10, 63, 64, 65, 11, 12, - 13, 14, 15, 22, 25, 38, 60, 67, 68, 69, - 71, 72, 74, 76, 88, 105, 6, 3, 4, 8, - 3, 66, 8, 70, 4, 73, 75, 4, 77, 106, - 4, 3, 8, 50, 50, 38, 4, 4, 39, 4, - 4, 7, 4, 4, 68, 4, 7, 38, 51, 53, - 38, 89, 5, 5, 50, 67, 16, 17, 18, 60, - 90, 91, 92, 94, 96, 7, 78, 79, 80, 7, - 107, 108, 8, 93, 95, 97, 3, 8, 81, 6, - 3, 109, 3, 6, 4, 4, 4, 91, 23, 24, - 60, 82, 83, 84, 86, 80, 26, 27, 29, 30, - 60, 72, 74, 110, 111, 112, 114, 115, 117, 108, - 7, 7, 7, 85, 87, 3, 8, 113, 118, 4, - 116, 3, 8, 19, 20, 60, 72, 74, 98, 99, - 100, 102, 98, 98, 4, 4, 83, 4, 4, 39, - 4, 111, 101, 103, 3, 8, 8, 8, 38, 53, - 38, 5, 38, 4, 4, 99, 7, 119, 120, 38, - 21, 104, 121, 3, 6, 28, 31, 32, 33, 34, - 122, 123, 124, 126, 127, 128, 129, 120, 125, 4, - 4, 4, 130, 3, 8, 4, 41, 39, 39, 4, - 123, 38, 38 + 0, 39, 40, 41, 47, 48, 49, 50, 0, 5, + 7, 9, 42, 43, 44, 45, 53, 54, 55, 60, + 7, 65, 7, 51, 61, 56, 66, 52, 54, 62, + 63, 42, 58, 59, 10, 67, 68, 69, 11, 12, + 13, 14, 15, 16, 23, 26, 29, 42, 64, 71, + 72, 73, 75, 76, 78, 80, 82, 94, 111, 123, + 6, 3, 4, 8, 3, 70, 8, 74, 4, 77, + 79, 81, 4, 112, 83, 124, 4, 3, 8, 54, + 54, 42, 4, 4, 43, 4, 4, 4, 7, 4, + 4, 4, 72, 4, 7, 42, 42, 55, 57, 42, + 95, 5, 5, 5, 54, 71, 17, 18, 19, 64, + 96, 97, 98, 100, 102, 7, 113, 114, 115, 7, + 84, 85, 86, 7, 125, 126, 8, 99, 101, 103, + 3, 8, 116, 6, 3, 87, 6, 3, 127, 3, + 6, 4, 4, 4, 97, 24, 25, 64, 78, 80, + 117, 118, 119, 121, 115, 27, 28, 64, 88, 89, + 90, 92, 86, 30, 31, 33, 34, 64, 78, 80, + 128, 129, 130, 132, 133, 135, 126, 7, 7, 7, + 120, 122, 3, 8, 91, 93, 3, 8, 131, 136, + 4, 134, 3, 8, 20, 21, 64, 78, 80, 104, + 105, 106, 108, 104, 104, 4, 4, 118, 4, 4, + 89, 4, 4, 43, 4, 129, 107, 109, 3, 8, + 8, 8, 42, 42, 42, 54, 42, 5, 42, 4, + 4, 105, 7, 137, 138, 42, 22, 110, 139, 3, + 6, 32, 35, 36, 37, 38, 140, 141, 142, 144, + 145, 146, 147, 138, 143, 4, 4, 4, 148, 3, + 8, 4, 45, 43, 43, 4, 141, 42, 42 }; const unsigned char AgentParser::yyr1_[] = { - 0, 42, 44, 43, 45, 43, 46, 43, 48, 47, - 49, 50, 50, 50, 50, 50, 50, 50, 52, 51, - 53, 54, 54, 55, 55, 57, 56, 58, 58, 59, - 59, 60, 62, 61, 63, 64, 66, 65, 67, 67, - 68, 68, 68, 68, 68, 68, 68, 68, 70, 69, - 71, 73, 72, 75, 74, 77, 76, 78, 78, 79, - 79, 81, 80, 82, 82, 82, 83, 83, 85, 84, - 87, 86, 89, 88, 90, 90, 91, 91, 91, 91, - 93, 92, 95, 94, 97, 96, 98, 98, 99, 99, - 99, 99, 99, 101, 100, 103, 102, 104, 106, 105, - 107, 107, 109, 108, 110, 110, 111, 111, 111, 111, - 111, 111, 111, 113, 112, 114, 116, 115, 118, 117, - 119, 119, 121, 120, 122, 122, 123, 123, 123, 123, - 123, 125, 124, 126, 127, 128, 130, 129 + 0, 46, 48, 47, 49, 47, 50, 47, 52, 51, + 53, 54, 54, 54, 54, 54, 54, 54, 56, 55, + 57, 58, 58, 59, 59, 61, 60, 62, 62, 63, + 63, 64, 66, 65, 67, 68, 70, 69, 71, 71, + 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, + 74, 73, 75, 77, 76, 79, 78, 81, 80, 83, + 82, 84, 84, 85, 85, 87, 86, 88, 88, 88, + 89, 89, 91, 90, 93, 92, 95, 94, 96, 96, + 97, 97, 97, 97, 99, 98, 101, 100, 103, 102, + 104, 104, 105, 105, 105, 105, 105, 107, 106, 109, + 108, 110, 112, 111, 113, 113, 114, 114, 116, 115, + 117, 117, 118, 118, 118, 118, 118, 120, 119, 122, + 121, 124, 123, 125, 125, 127, 126, 128, 128, 129, + 129, 129, 129, 129, 129, 129, 131, 130, 132, 134, + 133, 136, 135, 137, 137, 139, 138, 140, 140, 141, + 141, 141, 141, 141, 143, 142, 144, 145, 146, 148, + 147 }; const signed char @@ -1930,16 +2046,19 @@ namespace isc { namespace agent { 1, 1, 1, 1, 1, 1, 1, 1, 0, 4, 1, 0, 1, 3, 5, 0, 4, 0, 1, 1, 3, 2, 0, 4, 1, 1, 0, 6, 1, 3, - 1, 1, 1, 1, 1, 1, 1, 1, 0, 4, - 3, 0, 4, 0, 4, 0, 6, 0, 1, 1, - 3, 0, 4, 1, 3, 1, 1, 1, 0, 4, - 0, 4, 0, 6, 1, 3, 1, 1, 1, 1, - 0, 6, 0, 6, 0, 6, 1, 3, 1, 1, - 1, 1, 1, 0, 4, 0, 4, 1, 0, 6, - 1, 3, 0, 4, 1, 3, 1, 1, 1, 1, - 1, 1, 1, 0, 4, 3, 0, 4, 0, 6, - 1, 3, 0, 4, 1, 3, 1, 1, 1, 1, - 1, 0, 4, 3, 3, 3, 0, 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 4, 3, 0, 4, 0, 4, 0, 4, 0, + 6, 0, 1, 1, 3, 0, 4, 1, 3, 1, + 1, 1, 0, 4, 0, 4, 0, 6, 1, 3, + 1, 1, 1, 1, 0, 6, 0, 6, 0, 6, + 1, 3, 1, 1, 1, 1, 1, 0, 4, 0, + 4, 1, 0, 6, 0, 1, 1, 3, 0, 4, + 1, 3, 1, 1, 1, 1, 1, 0, 4, 0, + 4, 0, 6, 1, 3, 0, 4, 1, 3, 1, + 1, 1, 1, 1, 1, 1, 0, 4, 3, 0, + 4, 0, 6, 1, 3, 0, 4, 1, 3, 1, + 1, 1, 1, 1, 0, 4, 3, 3, 3, 0, + 4 }; @@ -1951,32 +2070,37 @@ namespace isc { namespace agent { { "\"end of file\"", "error", "\"invalid token\"", "\",\"", "\":\"", "\"[\"", "\"]\"", "\"{\"", "\"}\"", "\"null\"", "\"Control-agent\"", - "\"http-host\"", "\"http-port\"", "\"user-context\"", "\"comment\"", - "\"control-sockets\"", "\"dhcp4\"", "\"dhcp6\"", "\"d2\"", - "\"socket-name\"", "\"socket-type\"", "\"unix\"", "\"hooks-libraries\"", - "\"library\"", "\"parameters\"", "\"loggers\"", "\"name\"", - "\"output_options\"", "\"output\"", "\"debuglevel\"", "\"severity\"", - "\"flush\"", "\"maxsize\"", "\"maxver\"", "\"pattern\"", "START_JSON", - "START_AGENT", "START_SUB_AGENT", "\"constant string\"", "\"integer\"", - "\"floating point\"", "\"boolean\"", "$accept", "start", "$@1", "$@2", - "$@3", "sub_agent", "$@4", "json", "value", "map", "$@5", "map_value", - "map_content", "not_empty_map", "list_generic", "$@6", "list_content", - "not_empty_list", "unknown_map_entry", "agent_syntax_map", "$@7", - "global_objects", "global_object", "agent_object", "$@8", - "global_params", "global_param", "http_host", "$@9", "http_port", - "user_context", "$@10", "comment", "$@11", "hooks_libraries", "$@12", + "\"http-host\"", "\"http-port\"", "\"basic-authentication-realm\"", + "\"user-context\"", "\"comment\"", "\"control-sockets\"", "\"dhcp4\"", + "\"dhcp6\"", "\"d2\"", "\"socket-name\"", "\"socket-type\"", "\"unix\"", + "\"basic-authentications\"", "\"user\"", "\"password\"", + "\"hooks-libraries\"", "\"library\"", "\"parameters\"", "\"loggers\"", + "\"name\"", "\"output_options\"", "\"output\"", "\"debuglevel\"", + "\"severity\"", "\"flush\"", "\"maxsize\"", "\"maxver\"", "\"pattern\"", + "START_JSON", "START_AGENT", "START_SUB_AGENT", "\"constant string\"", + "\"integer\"", "\"floating point\"", "\"boolean\"", "$accept", "start", + "$@1", "$@2", "$@3", "sub_agent", "$@4", "json", "value", "map", "$@5", + "map_value", "map_content", "not_empty_map", "list_generic", "$@6", + "list_content", "not_empty_list", "unknown_map_entry", + "agent_syntax_map", "$@7", "global_objects", "global_object", + "agent_object", "$@8", "global_params", "global_param", "http_host", + "$@9", "http_port", "basic_authentication_realm", "$@10", "user_context", + "$@11", "comment", "$@12", "hooks_libraries", "$@13", "hooks_libraries_list", "not_empty_hooks_libraries_list", - "hooks_library", "$@13", "hooks_params", "hooks_param", "library", - "$@14", "parameters", "$@15", "control_sockets", "$@16", + "hooks_library", "$@14", "hooks_params", "hooks_param", "library", + "$@15", "parameters", "$@16", "control_sockets", "$@17", "control_sockets_params", "control_socket", "dhcp4_server_socket", - "$@17", "dhcp6_server_socket", "$@18", "d2_server_socket", "$@19", - "control_socket_params", "control_socket_param", "socket_name", "$@20", - "socket_type", "$@21", "socket_type_value", "loggers", "$@22", - "loggers_entries", "logger_entry", "$@23", "logger_params", - "logger_param", "name", "$@24", "debuglevel", "severity", "$@25", - "output_options_list", "$@26", "output_options_list_content", - "output_entry", "$@27", "output_params_list", "output_params", "output", - "$@28", "flush", "maxsize", "maxver", "pattern", "$@29", YY_NULLPTR + "$@18", "dhcp6_server_socket", "$@19", "d2_server_socket", "$@20", + "control_socket_params", "control_socket_param", "socket_name", "$@21", + "socket_type", "$@22", "socket_type_value", "basic_authentications", + "$@23", "basic_auth_list", "not_empty_basic_auth_list", "basic_auth", + "$@24", "basic_auth_params", "basic_auth_param", "user", "$@25", + "password", "$@26", "loggers", "$@27", "loggers_entries", "logger_entry", + "$@28", "logger_params", "logger_param", "name", "$@29", "debuglevel", + "severity", "$@30", "output_options_list", "$@31", + "output_options_list_content", "output_entry", "$@32", + "output_params_list", "output_params", "output", "$@33", "flush", + "maxsize", "maxver", "pattern", "$@34", YY_NULLPTR }; #endif @@ -1985,20 +2109,23 @@ namespace isc { namespace agent { const short AgentParser::yyrline_[] = { - 0, 110, 110, 110, 111, 111, 112, 112, 120, 120, - 131, 137, 138, 139, 140, 141, 142, 143, 147, 147, - 158, 163, 164, 172, 176, 183, 183, 189, 190, 193, - 197, 210, 218, 218, 230, 234, 238, 238, 255, 256, - 261, 262, 263, 264, 265, 266, 267, 268, 271, 271, - 279, 284, 284, 309, 309, 337, 337, 347, 348, 351, - 352, 355, 355, 363, 364, 365, 368, 369, 372, 372, - 380, 380, 390, 390, 403, 404, 409, 410, 411, 412, - 416, 416, 427, 427, 438, 438, 449, 450, 454, 455, - 456, 457, 458, 462, 462, 471, 471, 479, 486, 486, - 498, 499, 503, 503, 511, 512, 515, 516, 517, 518, - 519, 520, 521, 524, 524, 532, 537, 537, 545, 545, - 555, 556, 559, 559, 567, 568, 571, 572, 573, 574, - 575, 578, 578, 586, 591, 596, 601, 601 + 0, 115, 115, 115, 116, 116, 117, 117, 125, 125, + 136, 142, 143, 144, 145, 146, 147, 148, 152, 152, + 163, 168, 169, 177, 181, 188, 188, 194, 195, 198, + 202, 215, 223, 223, 235, 239, 243, 243, 260, 261, + 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, + 278, 278, 286, 291, 291, 299, 299, 324, 324, 352, + 352, 362, 363, 366, 367, 370, 370, 378, 379, 380, + 383, 384, 387, 387, 395, 395, 405, 405, 418, 419, + 424, 425, 426, 427, 431, 431, 442, 442, 453, 453, + 464, 465, 469, 470, 471, 472, 473, 477, 477, 486, + 486, 494, 501, 501, 511, 512, 515, 516, 519, 519, + 527, 528, 531, 532, 533, 534, 535, 538, 538, 546, + 546, 558, 558, 570, 571, 575, 575, 583, 584, 587, + 588, 589, 590, 591, 592, 593, 596, 596, 604, 609, + 609, 617, 617, 627, 628, 631, 631, 639, 640, 643, + 644, 645, 646, 647, 650, 650, 658, 663, 668, 673, + 673 }; void @@ -2031,9 +2158,9 @@ namespace isc { namespace agent { #line 14 "agent_parser.yy" } } // isc::agent -#line 2035 "agent_parser.cc" +#line 2162 "agent_parser.cc" -#line 609 "agent_parser.yy" +#line 681 "agent_parser.yy" void diff --git a/src/bin/agent/agent_parser.h b/src/bin/agent/agent_parser.h index 3307fe2ca5..45be92fb45 100644 --- a/src/bin/agent/agent_parser.h +++ b/src/bin/agent/agent_parser.h @@ -1,4 +1,4 @@ -// A Bison parser, made by GNU Bison 3.7.1. +// A Bison parser, made by GNU Bison 3.6.4. // Skeleton interface for Bison LALR(1) parsers in C++ @@ -490,35 +490,39 @@ namespace isc { namespace agent { TOKEN_CONTROL_AGENT = 265, // "Control-agent" TOKEN_HTTP_HOST = 266, // "http-host" TOKEN_HTTP_PORT = 267, // "http-port" - TOKEN_USER_CONTEXT = 268, // "user-context" - TOKEN_COMMENT = 269, // "comment" - TOKEN_CONTROL_SOCKETS = 270, // "control-sockets" - TOKEN_DHCP4_SERVER = 271, // "dhcp4" - TOKEN_DHCP6_SERVER = 272, // "dhcp6" - TOKEN_D2_SERVER = 273, // "d2" - TOKEN_SOCKET_NAME = 274, // "socket-name" - TOKEN_SOCKET_TYPE = 275, // "socket-type" - TOKEN_UNIX = 276, // "unix" - TOKEN_HOOKS_LIBRARIES = 277, // "hooks-libraries" - TOKEN_LIBRARY = 278, // "library" - TOKEN_PARAMETERS = 279, // "parameters" - TOKEN_LOGGERS = 280, // "loggers" - TOKEN_NAME = 281, // "name" - TOKEN_OUTPUT_OPTIONS = 282, // "output_options" - TOKEN_OUTPUT = 283, // "output" - TOKEN_DEBUGLEVEL = 284, // "debuglevel" - TOKEN_SEVERITY = 285, // "severity" - TOKEN_FLUSH = 286, // "flush" - TOKEN_MAXSIZE = 287, // "maxsize" - TOKEN_MAXVER = 288, // "maxver" - TOKEN_PATTERN = 289, // "pattern" - TOKEN_START_JSON = 290, // START_JSON - TOKEN_START_AGENT = 291, // START_AGENT - TOKEN_START_SUB_AGENT = 292, // START_SUB_AGENT - TOKEN_STRING = 293, // "constant string" - TOKEN_INTEGER = 294, // "integer" - TOKEN_FLOAT = 295, // "floating point" - TOKEN_BOOLEAN = 296 // "boolean" + TOKEN_BASIC_AUTHENTICATION_REALM = 268, // "basic-authentication-realm" + TOKEN_USER_CONTEXT = 269, // "user-context" + TOKEN_COMMENT = 270, // "comment" + TOKEN_CONTROL_SOCKETS = 271, // "control-sockets" + TOKEN_DHCP4_SERVER = 272, // "dhcp4" + TOKEN_DHCP6_SERVER = 273, // "dhcp6" + TOKEN_D2_SERVER = 274, // "d2" + TOKEN_SOCKET_NAME = 275, // "socket-name" + TOKEN_SOCKET_TYPE = 276, // "socket-type" + TOKEN_UNIX = 277, // "unix" + TOKEN_BASIC_AUTHENTICATIONS = 278, // "basic-authentications" + TOKEN_USER = 279, // "user" + TOKEN_PASSWORD = 280, // "password" + TOKEN_HOOKS_LIBRARIES = 281, // "hooks-libraries" + TOKEN_LIBRARY = 282, // "library" + TOKEN_PARAMETERS = 283, // "parameters" + TOKEN_LOGGERS = 284, // "loggers" + TOKEN_NAME = 285, // "name" + TOKEN_OUTPUT_OPTIONS = 286, // "output_options" + TOKEN_OUTPUT = 287, // "output" + TOKEN_DEBUGLEVEL = 288, // "debuglevel" + TOKEN_SEVERITY = 289, // "severity" + TOKEN_FLUSH = 290, // "flush" + TOKEN_MAXSIZE = 291, // "maxsize" + TOKEN_MAXVER = 292, // "maxver" + TOKEN_PATTERN = 293, // "pattern" + TOKEN_START_JSON = 294, // START_JSON + TOKEN_START_AGENT = 295, // START_AGENT + TOKEN_START_SUB_AGENT = 296, // START_SUB_AGENT + TOKEN_STRING = 297, // "constant string" + TOKEN_INTEGER = 298, // "integer" + TOKEN_FLOAT = 299, // "floating point" + TOKEN_BOOLEAN = 300 // "boolean" }; /// Backward compatibility alias (Bison 3.6). typedef token_kind_type yytokentype; @@ -535,7 +539,7 @@ namespace isc { namespace agent { { enum symbol_kind_type { - YYNTOKENS = 42, ///< Number of tokens. + YYNTOKENS = 46, ///< Number of tokens. S_YYEMPTY = -2, S_YYEOF = 0, // "end of file" S_YYerror = 1, // error @@ -550,124 +554,142 @@ namespace isc { namespace agent { S_CONTROL_AGENT = 10, // "Control-agent" S_HTTP_HOST = 11, // "http-host" S_HTTP_PORT = 12, // "http-port" - S_USER_CONTEXT = 13, // "user-context" - S_COMMENT = 14, // "comment" - S_CONTROL_SOCKETS = 15, // "control-sockets" - S_DHCP4_SERVER = 16, // "dhcp4" - S_DHCP6_SERVER = 17, // "dhcp6" - S_D2_SERVER = 18, // "d2" - S_SOCKET_NAME = 19, // "socket-name" - S_SOCKET_TYPE = 20, // "socket-type" - S_UNIX = 21, // "unix" - S_HOOKS_LIBRARIES = 22, // "hooks-libraries" - S_LIBRARY = 23, // "library" - S_PARAMETERS = 24, // "parameters" - S_LOGGERS = 25, // "loggers" - S_NAME = 26, // "name" - S_OUTPUT_OPTIONS = 27, // "output_options" - S_OUTPUT = 28, // "output" - S_DEBUGLEVEL = 29, // "debuglevel" - S_SEVERITY = 30, // "severity" - S_FLUSH = 31, // "flush" - S_MAXSIZE = 32, // "maxsize" - S_MAXVER = 33, // "maxver" - S_PATTERN = 34, // "pattern" - S_START_JSON = 35, // START_JSON - S_START_AGENT = 36, // START_AGENT - S_START_SUB_AGENT = 37, // START_SUB_AGENT - S_STRING = 38, // "constant string" - S_INTEGER = 39, // "integer" - S_FLOAT = 40, // "floating point" - S_BOOLEAN = 41, // "boolean" - S_YYACCEPT = 42, // $accept - S_start = 43, // start - S_44_1 = 44, // $@1 - S_45_2 = 45, // $@2 - S_46_3 = 46, // $@3 - S_sub_agent = 47, // sub_agent - S_48_4 = 48, // $@4 - S_json = 49, // json - S_value = 50, // value - S_map = 51, // map - S_52_5 = 52, // $@5 - S_map_value = 53, // map_value - S_map_content = 54, // map_content - S_not_empty_map = 55, // not_empty_map - S_list_generic = 56, // list_generic - S_57_6 = 57, // $@6 - S_list_content = 58, // list_content - S_not_empty_list = 59, // not_empty_list - S_unknown_map_entry = 60, // unknown_map_entry - S_agent_syntax_map = 61, // agent_syntax_map - S_62_7 = 62, // $@7 - S_global_objects = 63, // global_objects - S_global_object = 64, // global_object - S_agent_object = 65, // agent_object - S_66_8 = 66, // $@8 - S_global_params = 67, // global_params - S_global_param = 68, // global_param - S_http_host = 69, // http_host - S_70_9 = 70, // $@9 - S_http_port = 71, // http_port - S_user_context = 72, // user_context - S_73_10 = 73, // $@10 - S_comment = 74, // comment - S_75_11 = 75, // $@11 - S_hooks_libraries = 76, // hooks_libraries - S_77_12 = 77, // $@12 - S_hooks_libraries_list = 78, // hooks_libraries_list - S_not_empty_hooks_libraries_list = 79, // not_empty_hooks_libraries_list - S_hooks_library = 80, // hooks_library - S_81_13 = 81, // $@13 - S_hooks_params = 82, // hooks_params - S_hooks_param = 83, // hooks_param - S_library = 84, // library - S_85_14 = 85, // $@14 - S_parameters = 86, // parameters - S_87_15 = 87, // $@15 - S_control_sockets = 88, // control_sockets - S_89_16 = 89, // $@16 - S_control_sockets_params = 90, // control_sockets_params - S_control_socket = 91, // control_socket - S_dhcp4_server_socket = 92, // dhcp4_server_socket - S_93_17 = 93, // $@17 - S_dhcp6_server_socket = 94, // dhcp6_server_socket - S_95_18 = 95, // $@18 - S_d2_server_socket = 96, // d2_server_socket - S_97_19 = 97, // $@19 - S_control_socket_params = 98, // control_socket_params - S_control_socket_param = 99, // control_socket_param - S_socket_name = 100, // socket_name - S_101_20 = 101, // $@20 - S_socket_type = 102, // socket_type - S_103_21 = 103, // $@21 - S_socket_type_value = 104, // socket_type_value - S_loggers = 105, // loggers - S_106_22 = 106, // $@22 - S_loggers_entries = 107, // loggers_entries - S_logger_entry = 108, // logger_entry - S_109_23 = 109, // $@23 - S_logger_params = 110, // logger_params - S_logger_param = 111, // logger_param - S_name = 112, // name - S_113_24 = 113, // $@24 - S_debuglevel = 114, // debuglevel - S_severity = 115, // severity - S_116_25 = 116, // $@25 - S_output_options_list = 117, // output_options_list - S_118_26 = 118, // $@26 - S_output_options_list_content = 119, // output_options_list_content - S_output_entry = 120, // output_entry - S_121_27 = 121, // $@27 - S_output_params_list = 122, // output_params_list - S_output_params = 123, // output_params - S_output = 124, // output - S_125_28 = 125, // $@28 - S_flush = 126, // flush - S_maxsize = 127, // maxsize - S_maxver = 128, // maxver - S_pattern = 129, // pattern - S_130_29 = 130 // $@29 + S_BASIC_AUTHENTICATION_REALM = 13, // "basic-authentication-realm" + S_USER_CONTEXT = 14, // "user-context" + S_COMMENT = 15, // "comment" + S_CONTROL_SOCKETS = 16, // "control-sockets" + S_DHCP4_SERVER = 17, // "dhcp4" + S_DHCP6_SERVER = 18, // "dhcp6" + S_D2_SERVER = 19, // "d2" + S_SOCKET_NAME = 20, // "socket-name" + S_SOCKET_TYPE = 21, // "socket-type" + S_UNIX = 22, // "unix" + S_BASIC_AUTHENTICATIONS = 23, // "basic-authentications" + S_USER = 24, // "user" + S_PASSWORD = 25, // "password" + S_HOOKS_LIBRARIES = 26, // "hooks-libraries" + S_LIBRARY = 27, // "library" + S_PARAMETERS = 28, // "parameters" + S_LOGGERS = 29, // "loggers" + S_NAME = 30, // "name" + S_OUTPUT_OPTIONS = 31, // "output_options" + S_OUTPUT = 32, // "output" + S_DEBUGLEVEL = 33, // "debuglevel" + S_SEVERITY = 34, // "severity" + S_FLUSH = 35, // "flush" + S_MAXSIZE = 36, // "maxsize" + S_MAXVER = 37, // "maxver" + S_PATTERN = 38, // "pattern" + S_START_JSON = 39, // START_JSON + S_START_AGENT = 40, // START_AGENT + S_START_SUB_AGENT = 41, // START_SUB_AGENT + S_STRING = 42, // "constant string" + S_INTEGER = 43, // "integer" + S_FLOAT = 44, // "floating point" + S_BOOLEAN = 45, // "boolean" + S_YYACCEPT = 46, // $accept + S_start = 47, // start + S_48_1 = 48, // $@1 + S_49_2 = 49, // $@2 + S_50_3 = 50, // $@3 + S_sub_agent = 51, // sub_agent + S_52_4 = 52, // $@4 + S_json = 53, // json + S_value = 54, // value + S_map = 55, // map + S_56_5 = 56, // $@5 + S_map_value = 57, // map_value + S_map_content = 58, // map_content + S_not_empty_map = 59, // not_empty_map + S_list_generic = 60, // list_generic + S_61_6 = 61, // $@6 + S_list_content = 62, // list_content + S_not_empty_list = 63, // not_empty_list + S_unknown_map_entry = 64, // unknown_map_entry + S_agent_syntax_map = 65, // agent_syntax_map + S_66_7 = 66, // $@7 + S_global_objects = 67, // global_objects + S_global_object = 68, // global_object + S_agent_object = 69, // agent_object + S_70_8 = 70, // $@8 + S_global_params = 71, // global_params + S_global_param = 72, // global_param + S_http_host = 73, // http_host + S_74_9 = 74, // $@9 + S_http_port = 75, // http_port + S_basic_authentication_realm = 76, // basic_authentication_realm + S_77_10 = 77, // $@10 + S_user_context = 78, // user_context + S_79_11 = 79, // $@11 + S_comment = 80, // comment + S_81_12 = 81, // $@12 + S_hooks_libraries = 82, // hooks_libraries + S_83_13 = 83, // $@13 + S_hooks_libraries_list = 84, // hooks_libraries_list + S_not_empty_hooks_libraries_list = 85, // not_empty_hooks_libraries_list + S_hooks_library = 86, // hooks_library + S_87_14 = 87, // $@14 + S_hooks_params = 88, // hooks_params + S_hooks_param = 89, // hooks_param + S_library = 90, // library + S_91_15 = 91, // $@15 + S_parameters = 92, // parameters + S_93_16 = 93, // $@16 + S_control_sockets = 94, // control_sockets + S_95_17 = 95, // $@17 + S_control_sockets_params = 96, // control_sockets_params + S_control_socket = 97, // control_socket + S_dhcp4_server_socket = 98, // dhcp4_server_socket + S_99_18 = 99, // $@18 + S_dhcp6_server_socket = 100, // dhcp6_server_socket + S_101_19 = 101, // $@19 + S_d2_server_socket = 102, // d2_server_socket + S_103_20 = 103, // $@20 + S_control_socket_params = 104, // control_socket_params + S_control_socket_param = 105, // control_socket_param + S_socket_name = 106, // socket_name + S_107_21 = 107, // $@21 + S_socket_type = 108, // socket_type + S_109_22 = 109, // $@22 + S_socket_type_value = 110, // socket_type_value + S_basic_authentications = 111, // basic_authentications + S_112_23 = 112, // $@23 + S_basic_auth_list = 113, // basic_auth_list + S_not_empty_basic_auth_list = 114, // not_empty_basic_auth_list + S_basic_auth = 115, // basic_auth + S_116_24 = 116, // $@24 + S_basic_auth_params = 117, // basic_auth_params + S_basic_auth_param = 118, // basic_auth_param + S_user = 119, // user + S_120_25 = 120, // $@25 + S_password = 121, // password + S_122_26 = 122, // $@26 + S_loggers = 123, // loggers + S_124_27 = 124, // $@27 + S_loggers_entries = 125, // loggers_entries + S_logger_entry = 126, // logger_entry + S_127_28 = 127, // $@28 + S_logger_params = 128, // logger_params + S_logger_param = 129, // logger_param + S_name = 130, // name + S_131_29 = 131, // $@29 + S_debuglevel = 132, // debuglevel + S_severity = 133, // severity + S_134_30 = 134, // $@30 + S_output_options_list = 135, // output_options_list + S_136_31 = 136, // $@31 + S_output_options_list_content = 137, // output_options_list_content + S_output_entry = 138, // output_entry + S_139_32 = 139, // $@32 + S_output_params_list = 140, // output_params_list + S_output_params = 141, // output_params + S_output = 142, // output + S_143_33 = 143, // $@33 + S_flush = 144, // flush + S_maxsize = 145, // maxsize + S_maxver = 146, // maxver + S_pattern = 147, // pattern + S_148_34 = 148 // $@34 }; }; @@ -704,25 +726,25 @@ namespace isc { namespace agent { { switch (this->kind ()) { - case symbol_kind::S_value: // value - case symbol_kind::S_map_value: // map_value - case symbol_kind::S_socket_type_value: // socket_type_value + case 54: // value + case 57: // map_value + case 110: // socket_type_value value.move< ElementPtr > (std::move (that.value)); break; - case symbol_kind::S_BOOLEAN: // "boolean" + case 45: // "boolean" value.move< bool > (std::move (that.value)); break; - case symbol_kind::S_FLOAT: // "floating point" + case 44: // "floating point" value.move< double > (std::move (that.value)); break; - case symbol_kind::S_INTEGER: // "integer" + case 43: // "integer" value.move< int64_t > (std::move (that.value)); break; - case symbol_kind::S_STRING: // "constant string" + case 42: // "constant string" value.move< std::string > (std::move (that.value)); break; @@ -836,25 +858,25 @@ namespace isc { namespace agent { // Value type destructor. switch (yykind) { - case symbol_kind::S_value: // value - case symbol_kind::S_map_value: // map_value - case symbol_kind::S_socket_type_value: // socket_type_value + case 54: // value + case 57: // map_value + case 110: // socket_type_value value.template destroy< ElementPtr > (); break; - case symbol_kind::S_BOOLEAN: // "boolean" + case 45: // "boolean" value.template destroy< bool > (); break; - case symbol_kind::S_FLOAT: // "floating point" + case 44: // "floating point" value.template destroy< double > (); break; - case symbol_kind::S_INTEGER: // "integer" + case 43: // "integer" value.template destroy< int64_t > (); break; - case symbol_kind::S_STRING: // "constant string" + case 42: // "constant string" value.template destroy< std::string > (); break; @@ -948,13 +970,13 @@ switch (yykind) symbol_type (int tok, location_type l) : super_type(token_type (tok), std::move (l)) { - YY_ASSERT (tok == token::TOKEN_END || tok == token::TOKEN_AGENT_error || tok == token::TOKEN_AGENT_UNDEF || tok == token::TOKEN_COMMA || tok == token::TOKEN_COLON || tok == token::TOKEN_LSQUARE_BRACKET || tok == token::TOKEN_RSQUARE_BRACKET || tok == token::TOKEN_LCURLY_BRACKET || tok == token::TOKEN_RCURLY_BRACKET || tok == token::TOKEN_NULL_TYPE || tok == token::TOKEN_CONTROL_AGENT || tok == token::TOKEN_HTTP_HOST || tok == token::TOKEN_HTTP_PORT || tok == token::TOKEN_USER_CONTEXT || tok == token::TOKEN_COMMENT || tok == token::TOKEN_CONTROL_SOCKETS || tok == token::TOKEN_DHCP4_SERVER || tok == token::TOKEN_DHCP6_SERVER || tok == token::TOKEN_D2_SERVER || tok == token::TOKEN_SOCKET_NAME || tok == token::TOKEN_SOCKET_TYPE || tok == token::TOKEN_UNIX || tok == token::TOKEN_HOOKS_LIBRARIES || tok == token::TOKEN_LIBRARY || tok == token::TOKEN_PARAMETERS || tok == token::TOKEN_LOGGERS || tok == token::TOKEN_NAME || tok == token::TOKEN_OUTPUT_OPTIONS || tok == token::TOKEN_OUTPUT || tok == token::TOKEN_DEBUGLEVEL || tok == token::TOKEN_SEVERITY || tok == token::TOKEN_FLUSH || tok == token::TOKEN_MAXSIZE || tok == token::TOKEN_MAXVER || tok == token::TOKEN_PATTERN || tok == token::TOKEN_START_JSON || tok == token::TOKEN_START_AGENT || tok == token::TOKEN_START_SUB_AGENT); + YY_ASSERT (tok == token::TOKEN_END || tok == token::TOKEN_AGENT_error || tok == token::TOKEN_AGENT_UNDEF || tok == token::TOKEN_COMMA || tok == token::TOKEN_COLON || tok == token::TOKEN_LSQUARE_BRACKET || tok == token::TOKEN_RSQUARE_BRACKET || tok == token::TOKEN_LCURLY_BRACKET || tok == token::TOKEN_RCURLY_BRACKET || tok == token::TOKEN_NULL_TYPE || tok == token::TOKEN_CONTROL_AGENT || tok == token::TOKEN_HTTP_HOST || tok == token::TOKEN_HTTP_PORT || tok == token::TOKEN_BASIC_AUTHENTICATION_REALM || tok == token::TOKEN_USER_CONTEXT || tok == token::TOKEN_COMMENT || tok == token::TOKEN_CONTROL_SOCKETS || tok == token::TOKEN_DHCP4_SERVER || tok == token::TOKEN_DHCP6_SERVER || tok == token::TOKEN_D2_SERVER || tok == token::TOKEN_SOCKET_NAME || tok == token::TOKEN_SOCKET_TYPE || tok == token::TOKEN_UNIX || tok == token::TOKEN_BASIC_AUTHENTICATIONS || tok == token::TOKEN_USER || tok == token::TOKEN_PASSWORD || tok == token::TOKEN_HOOKS_LIBRARIES || tok == token::TOKEN_LIBRARY || tok == token::TOKEN_PARAMETERS || tok == token::TOKEN_LOGGERS || tok == token::TOKEN_NAME || tok == token::TOKEN_OUTPUT_OPTIONS || tok == token::TOKEN_OUTPUT || tok == token::TOKEN_DEBUGLEVEL || tok == token::TOKEN_SEVERITY || tok == token::TOKEN_FLUSH || tok == token::TOKEN_MAXSIZE || tok == token::TOKEN_MAXVER || tok == token::TOKEN_PATTERN || tok == token::TOKEN_START_JSON || tok == token::TOKEN_START_AGENT || tok == token::TOKEN_START_SUB_AGENT); } #else symbol_type (int tok, const location_type& l) : super_type(token_type (tok), l) { - YY_ASSERT (tok == token::TOKEN_END || tok == token::TOKEN_AGENT_error || tok == token::TOKEN_AGENT_UNDEF || tok == token::TOKEN_COMMA || tok == token::TOKEN_COLON || tok == token::TOKEN_LSQUARE_BRACKET || tok == token::TOKEN_RSQUARE_BRACKET || tok == token::TOKEN_LCURLY_BRACKET || tok == token::TOKEN_RCURLY_BRACKET || tok == token::TOKEN_NULL_TYPE || tok == token::TOKEN_CONTROL_AGENT || tok == token::TOKEN_HTTP_HOST || tok == token::TOKEN_HTTP_PORT || tok == token::TOKEN_USER_CONTEXT || tok == token::TOKEN_COMMENT || tok == token::TOKEN_CONTROL_SOCKETS || tok == token::TOKEN_DHCP4_SERVER || tok == token::TOKEN_DHCP6_SERVER || tok == token::TOKEN_D2_SERVER || tok == token::TOKEN_SOCKET_NAME || tok == token::TOKEN_SOCKET_TYPE || tok == token::TOKEN_UNIX || tok == token::TOKEN_HOOKS_LIBRARIES || tok == token::TOKEN_LIBRARY || tok == token::TOKEN_PARAMETERS || tok == token::TOKEN_LOGGERS || tok == token::TOKEN_NAME || tok == token::TOKEN_OUTPUT_OPTIONS || tok == token::TOKEN_OUTPUT || tok == token::TOKEN_DEBUGLEVEL || tok == token::TOKEN_SEVERITY || tok == token::TOKEN_FLUSH || tok == token::TOKEN_MAXSIZE || tok == token::TOKEN_MAXVER || tok == token::TOKEN_PATTERN || tok == token::TOKEN_START_JSON || tok == token::TOKEN_START_AGENT || tok == token::TOKEN_START_SUB_AGENT); + YY_ASSERT (tok == token::TOKEN_END || tok == token::TOKEN_AGENT_error || tok == token::TOKEN_AGENT_UNDEF || tok == token::TOKEN_COMMA || tok == token::TOKEN_COLON || tok == token::TOKEN_LSQUARE_BRACKET || tok == token::TOKEN_RSQUARE_BRACKET || tok == token::TOKEN_LCURLY_BRACKET || tok == token::TOKEN_RCURLY_BRACKET || tok == token::TOKEN_NULL_TYPE || tok == token::TOKEN_CONTROL_AGENT || tok == token::TOKEN_HTTP_HOST || tok == token::TOKEN_HTTP_PORT || tok == token::TOKEN_BASIC_AUTHENTICATION_REALM || tok == token::TOKEN_USER_CONTEXT || tok == token::TOKEN_COMMENT || tok == token::TOKEN_CONTROL_SOCKETS || tok == token::TOKEN_DHCP4_SERVER || tok == token::TOKEN_DHCP6_SERVER || tok == token::TOKEN_D2_SERVER || tok == token::TOKEN_SOCKET_NAME || tok == token::TOKEN_SOCKET_TYPE || tok == token::TOKEN_UNIX || tok == token::TOKEN_BASIC_AUTHENTICATIONS || tok == token::TOKEN_USER || tok == token::TOKEN_PASSWORD || tok == token::TOKEN_HOOKS_LIBRARIES || tok == token::TOKEN_LIBRARY || tok == token::TOKEN_PARAMETERS || tok == token::TOKEN_LOGGERS || tok == token::TOKEN_NAME || tok == token::TOKEN_OUTPUT_OPTIONS || tok == token::TOKEN_OUTPUT || tok == token::TOKEN_DEBUGLEVEL || tok == token::TOKEN_SEVERITY || tok == token::TOKEN_FLUSH || tok == token::TOKEN_MAXSIZE || tok == token::TOKEN_MAXVER || tok == token::TOKEN_PATTERN || tok == token::TOKEN_START_JSON || tok == token::TOKEN_START_AGENT || tok == token::TOKEN_START_SUB_AGENT); } #endif #if 201103L <= YY_CPLUSPLUS @@ -1252,6 +1274,21 @@ switch (yykind) return symbol_type (token::TOKEN_HTTP_PORT, l); } #endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_BASIC_AUTHENTICATION_REALM (location_type l) + { + return symbol_type (token::TOKEN_BASIC_AUTHENTICATION_REALM, std::move (l)); + } +#else + static + symbol_type + make_BASIC_AUTHENTICATION_REALM (const location_type& l) + { + return symbol_type (token::TOKEN_BASIC_AUTHENTICATION_REALM, l); + } +#endif #if 201103L <= YY_CPLUSPLUS static symbol_type @@ -1387,6 +1424,51 @@ switch (yykind) return symbol_type (token::TOKEN_UNIX, l); } #endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_BASIC_AUTHENTICATIONS (location_type l) + { + return symbol_type (token::TOKEN_BASIC_AUTHENTICATIONS, std::move (l)); + } +#else + static + symbol_type + make_BASIC_AUTHENTICATIONS (const location_type& l) + { + return symbol_type (token::TOKEN_BASIC_AUTHENTICATIONS, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_USER (location_type l) + { + return symbol_type (token::TOKEN_USER, std::move (l)); + } +#else + static + symbol_type + make_USER (const location_type& l) + { + return symbol_type (token::TOKEN_USER, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_PASSWORD (location_type l) + { + return symbol_type (token::TOKEN_PASSWORD, std::move (l)); + } +#else + static + symbol_type + make_PASSWORD (const location_type& l) + { + return symbol_type (token::TOKEN_PASSWORD, l); + } +#endif #if 201103L <= YY_CPLUSPLUS static symbol_type @@ -1717,7 +1799,7 @@ switch (yykind) /// Stored state numbers (used for stacks). - typedef unsigned char state_type; + typedef short state_type; /// The arguments of the error message. int yy_syntax_error_arguments_ (const context& yyctx, @@ -1739,7 +1821,7 @@ switch (yykind) /// \param yyvalue the value to check static bool yy_table_value_is_error_ (int yyvalue); - static const short yypact_ninf_; + static const signed char yypact_ninf_; static const signed char yytable_ninf_; /// Convert a scanner token kind \a t to a symbol kind. @@ -1765,7 +1847,7 @@ switch (yykind) static const unsigned char yydefact_[]; // YYPGOTO[NTERM-NUM]. - static const short yypgoto_[]; + static const signed char yypgoto_[]; // YYDEFGOTO[NTERM-NUM]. static const short yydefgoto_[]; @@ -1773,9 +1855,9 @@ switch (yykind) // YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM. If // positive, shift that token. If negative, reduce the rule whose // number is the opposite. If YYTABLE_NINF, syntax error. - static const unsigned char yytable_[]; + static const short yytable_[]; - static const unsigned char yycheck_[]; + static const short yycheck_[]; // YYSTOS[STATE-NUM] -- The (internal number of the) accessing // symbol of state STATE-NUM. @@ -1838,7 +1920,7 @@ switch (yykind) void move (by_state& that); /// The symbol kind (corresponding to \a state). - /// \a symbol_kind::S_YYEMPTY when empty. + /// \a S_YYEMPTY when empty. symbol_kind_type kind () const YY_NOEXCEPT; /// The state number used to denote an empty symbol. @@ -2017,8 +2099,8 @@ switch (yykind) /// Constants. enum { - yylast_ = 168, ///< Last index in yytable_. - yynnts_ = 89, ///< Number of nonterminal symbols. + yylast_ = 203, ///< Last index in yytable_. + yynnts_ = 103, ///< Number of nonterminal symbols. yyfinal_ = 8 ///< Termination state number. }; @@ -2067,14 +2149,14 @@ switch (yykind) 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, - 35, 36, 37, 38, 39, 40, 41 + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45 }; - // Last valid token kind. - const int code_max = 296; + const int user_token_number_max_ = 300; if (t <= 0) return symbol_kind::S_YYEOF; - else if (t <= code_max) + else if (t <= user_token_number_max_) return YY_CAST (symbol_kind_type, translate_table[t]); else return symbol_kind::S_YYUNDEF; @@ -2089,25 +2171,25 @@ switch (yykind) { switch (this->kind ()) { - case symbol_kind::S_value: // value - case symbol_kind::S_map_value: // map_value - case symbol_kind::S_socket_type_value: // socket_type_value + case 54: // value + case 57: // map_value + case 110: // socket_type_value value.copy< ElementPtr > (YY_MOVE (that.value)); break; - case symbol_kind::S_BOOLEAN: // "boolean" + case 45: // "boolean" value.copy< bool > (YY_MOVE (that.value)); break; - case symbol_kind::S_FLOAT: // "floating point" + case 44: // "floating point" value.copy< double > (YY_MOVE (that.value)); break; - case symbol_kind::S_INTEGER: // "integer" + case 43: // "integer" value.copy< int64_t > (YY_MOVE (that.value)); break; - case symbol_kind::S_STRING: // "constant string" + case 42: // "constant string" value.copy< std::string > (YY_MOVE (that.value)); break; @@ -2140,25 +2222,25 @@ switch (yykind) super_type::move (s); switch (this->kind ()) { - case symbol_kind::S_value: // value - case symbol_kind::S_map_value: // map_value - case symbol_kind::S_socket_type_value: // socket_type_value + case 54: // value + case 57: // map_value + case 110: // socket_type_value value.move< ElementPtr > (YY_MOVE (s.value)); break; - case symbol_kind::S_BOOLEAN: // "boolean" + case 45: // "boolean" value.move< bool > (YY_MOVE (s.value)); break; - case symbol_kind::S_FLOAT: // "floating point" + case 44: // "floating point" value.move< double > (YY_MOVE (s.value)); break; - case symbol_kind::S_INTEGER: // "integer" + case 43: // "integer" value.move< int64_t > (YY_MOVE (s.value)); break; - case symbol_kind::S_STRING: // "constant string" + case 42: // "constant string" value.move< std::string > (YY_MOVE (s.value)); break; @@ -2225,7 +2307,8 @@ switch (yykind) #line 14 "agent_parser.yy" } } // isc::agent -#line 2229 "agent_parser.h" +#line 2311 "agent_parser.h" + -- GitLab From 0fc1cd514def1b4e9d90afc1402666f6ab7d441c Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Sun, 12 Jul 2020 14:58:32 +0200 Subject: [PATCH 09/33] [#1304] Added config/parse --- doc/examples/agent/comments.json | 11 + doc/examples/agent/simple.json | 22 ++ src/bin/agent/ca_cfg_mgr.cc | 9 +- src/bin/agent/ca_cfg_mgr.h | 19 +- src/bin/agent/simple_parser.cc | 9 +- src/lib/http/Makefile.am | 4 + src/lib/http/basic_auth_config.cc | 137 +++++++++++ src/lib/http/basic_auth_config.h | 120 ++++++++++ src/lib/http/response_creator_auth.h | 4 +- src/lib/http/tests/Makefile.am | 1 + .../http/tests/basic_auth_config_unittests.cc | 218 ++++++++++++++++++ 11 files changed, 546 insertions(+), 8 deletions(-) create mode 100644 src/lib/http/basic_auth_config.cc create mode 100644 src/lib/http/basic_auth_config.h create mode 100644 src/lib/http/tests/basic_auth_config_unittests.cc diff --git a/doc/examples/agent/comments.json b/doc/examples/agent/comments.json index 1f90e1ce55..d0c6a00285 100644 --- a/doc/examples/agent/comments.json +++ b/doc/examples/agent/comments.json @@ -10,6 +10,17 @@ "http-host": "127.0.0.1", "http-port": 8000, + "basic-authentication-realm": "kea-control-agent", + + // In basoc HTTP authentication + "basic-authentications": + [ + { + "comment": "admin is authorized", + "user": "admin", + "password": "1234" + } + ], // In control socket "control-sockets": diff --git a/doc/examples/agent/simple.json b/doc/examples/agent/simple.json index 7bde939e8f..db37248568 100644 --- a/doc/examples/agent/simple.json +++ b/doc/examples/agent/simple.json @@ -11,6 +11,28 @@ // Another mandatory parameter is the HTTP port. "http-port": 8000, + // An optional parameter is the basic HTTP authentication realm. + // Its default is "kea-control-agent". + "basic-authentication-realm": "kea-control-agent", + + // This list specifies the user ids and passwords to use for + // basic HTTP authentication. If empty or not present any client + // is authorized. + "basic-authentications": + [ + // This specifies an authorized client. + { + "comment": "admin is authorized", + + // The user id must not be empty or contain the ':' character. + // It is a mandatory parameter. + "user": "admin", + + // If password is not specified an empty password is used. + "password": "1234" + } + ], + // This map specifies where control channel of each server is configured // to listen on. See 'control-socket' object in the respective // servers. At this time the only supported socket type is "unix". diff --git a/src/bin/agent/ca_cfg_mgr.cc b/src/bin/agent/ca_cfg_mgr.cc index 5bf87e5e94..fc013113ad 100644 --- a/src/bin/agent/ca_cfg_mgr.cc +++ b/src/bin/agent/ca_cfg_mgr.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2016-2019 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2016-2020 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -21,7 +21,7 @@ namespace isc { namespace agent { CtrlAgentCfgContext::CtrlAgentCfgContext() - :http_host_(""), http_port_(0) { + : http_host_(""), http_port_(0), basic_auth_realm_("") { } CtrlAgentCfgContext::CtrlAgentCfgContext(const CtrlAgentCfgContext& orig) @@ -50,6 +50,8 @@ CtrlAgentCfgMgr::getConfigSummary(const uint32_t /*selection*/) { // Then print the control-sockets s << ctx->getControlSocketInfoSummary(); + // @todo: add something if authentication is required + // Finally, print the hook libraries names const isc::hooks::HookLibsCollection libs = ctx->getHooksConfig().get(); s << ", " << libs.size() << " lib(s):"; @@ -152,6 +154,8 @@ CtrlAgentCfgContext::toElement() const { ca->set("http-host", Element::create(http_host_)); // Set http-port ca->set("http-port", Element::create(static_cast(http_port_))); + // Set basic-authentication-realm + ca->set("basic-authentication-realm", Element::create(basic_auth_realm_)); // Set hooks-libraries ca->set("hooks-libraries", hooks_config_.toElement()); // Set control-sockets @@ -161,6 +165,7 @@ CtrlAgentCfgContext::toElement() const { control_sockets->set(si->first, socket); } ca->set("control-sockets", control_sockets); + // @todo: Set authentication. // Set Control-agent ElementPtr result = Element::createMap(); result->set("Control-agent", ca); diff --git a/src/bin/agent/ca_cfg_mgr.h b/src/bin/agent/ca_cfg_mgr.h index 27c8c02a64..74de00b277 100644 --- a/src/bin/agent/ca_cfg_mgr.h +++ b/src/bin/agent/ca_cfg_mgr.h @@ -1,4 +1,4 @@ -// Copyright (C) 2016-2018 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2016-2020 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -98,6 +98,20 @@ public: return (http_port_); } + /// @brief Sets basic-authentication-realm parameter + /// + /// @param real Basic HTTP authentication realm + void setBasicAuthRealm(const std::string& realm) { + basic_auth_realm_ = realm; + } + + /// @brief Returns basic-authentication-realm parameter + /// + /// @return Basic HTTP authentication realm. + std::string getBasicAuthRealm() const { + return (basic_auth_realm_); + } + /// @brief Returns non-const reference to configured hooks libraries. /// /// @return non-const reference to configured hooks libraries. @@ -147,6 +161,9 @@ private: /// TCP port the CA should listen on. uint16_t http_port_; + /// Basic HTTP authentication realm. + std::string basic_auth_realm_; + /// @brief Configured hooks libraries. isc::hooks::HooksConfig hooks_config_; }; diff --git a/src/bin/agent/simple_parser.cc b/src/bin/agent/simple_parser.cc index 7f79439e46..14062dc589 100644 --- a/src/bin/agent/simple_parser.cc +++ b/src/bin/agent/simple_parser.cc @@ -36,8 +36,9 @@ namespace agent { /// /// These are global Control Agent parameters. const SimpleDefaults AgentSimpleParser::AGENT_DEFAULTS = { - { "http-host", Element::string, "127.0.0.1"}, - { "http-port", Element::integer, "8000"} + { "http-host", Element::string, "127.0.0.1" }, + { "http-port", Element::integer, "8000" }, + { "basic-authentication-realm", Element::string, "kea-control-agent" } }; /// @brief This table defines default values for control sockets. @@ -88,6 +89,8 @@ AgentSimpleParser::parse(const CtrlAgentCfgContextPtr& ctx, // Let's get the HTTP parameters first. ctx->setHttpHost(SimpleParser::getString(config, "http-host")); ctx->setHttpPort(SimpleParser::getIntType(config, "http-port")); + ctx->setBasicAuthRealm(SimpleParser::getString(config, + "basic-authentication-realm")); // Control sockets are second. ConstElementPtr ctrl_sockets = config->get("control-sockets"); @@ -98,6 +101,8 @@ AgentSimpleParser::parse(const CtrlAgentCfgContextPtr& ctx, } } + // Basic HTTP authentications are third. + // User context can be done at anytime. ConstElementPtr user_context = config->get("user-context"); if (user_context) { diff --git a/src/lib/http/Makefile.am b/src/lib/http/Makefile.am index 64c07b7775..34e5f500ec 100644 --- a/src/lib/http/Makefile.am +++ b/src/lib/http/Makefile.am @@ -40,6 +40,7 @@ libkea_http_la_SOURCES += response_creator_factory.h libkea_http_la_SOURCES += response_json.cc response_json.h libkea_http_la_SOURCES += url.cc url.h libkea_http_la_SOURCES += basic_auth.cc basic_auth.h +libkea_http_la_SOURCES += basic_auth_config.cc basic_auth_config.h libkea_http_la_CXXFLAGS = $(AM_CXXFLAGS) libkea_http_la_CPPFLAGS = $(AM_CPPFLAGS) @@ -90,6 +91,8 @@ endif # Specify the headers for copying into the installation directory tree. libkea_http_includedir = $(pkgincludedir)/http libkea_http_include_HEADERS = \ + basic_auth.h \ + basic_auth_config.h \ client.h \ connection.h \ connection_pool.h \ @@ -112,6 +115,7 @@ libkea_http_include_HEADERS = \ response.h \ response_context.h \ response_creator.h \ + response_creator_auth.h \ response_creator_factory.h \ response_json.h \ response_parser.h \ diff --git a/src/lib/http/basic_auth_config.cc b/src/lib/http/basic_auth_config.cc new file mode 100644 index 0000000000..d6213f5465 --- /dev/null +++ b/src/lib/http/basic_auth_config.cc @@ -0,0 +1,137 @@ +// Copyright (C) 2020 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include + +#include + +using namespace isc; +using namespace isc::data; +using namespace isc::dhcp; +using namespace std; + +namespace isc { +namespace http { + +BasicHttpAuthClient::BasicHttpAuthClient(const std::string& user, + const std::string& password, + const isc::data::ConstElementPtr& user_context) + : user_(user), password_(password) { + if (user_context) { + setContext(user_context); + } +} + +ElementPtr +BasicHttpAuthClient::toElement() const { + ElementPtr result = Element::createMap(); + + // Set user-context + contextToElement(result); + + // Set user + result->set("user", Element::create(user_)); + + // Set password + result->set("password", Element::create(password_)); + + return (result); +} + +void +BasicHttpAuthConfig::add(const std::string& user, + const std::string& password, + const ConstElementPtr& user_context) { + BasicHttpAuth basic_auth(user, password); + list_.push_back(BasicHttpAuthClient(user, password, user_context)); + map_[basic_auth.getCredential()] = user; +} + +void +BasicHttpAuthConfig::clear() { + list_.clear(); + map_.clear(); +} + +ElementPtr +BasicHttpAuthConfig::toElement() const { + ElementPtr result = Element::createList(); + + for (auto client : list_) { + result->add(client.toElement()); + } + + return (result); +} + +void +BasicHttpAuthConfig::parse(const ConstElementPtr& config) { + if (!config) { + return; + } + if (config->getType() != Element::list) { + isc_throw(DhcpConfigError, "basic-authentications must be a list (" + << config->getPosition() << ")"); + } + for (auto client : config->listValue()) { + if (client->getType() != Element::map) { + isc_throw(DhcpConfigError, "basic-authentications items must be " + << "maps (" << client->getPosition() << ")"); + } + + // user + ConstElementPtr user_cfg = client->get("user"); + if (!user_cfg) { + isc_throw(DhcpConfigError, "user is required in " + << "basic-authentications items (" + << client->getPosition() << ")"); + } + if (user_cfg->getType() != Element::string) { + isc_throw(DhcpConfigError, "user must be a string (" + << user_cfg->getPosition() << ")"); + } + string user = user_cfg->stringValue(); + if (user.empty()) { + isc_throw(DhcpConfigError, "user must be not be empty (" + << user_cfg->getPosition() << ")"); + } + if (user.find(':') != string::npos) { + isc_throw(DhcpConfigError, "user must not contain a ':': '" + << user << "' (" << user_cfg->getPosition() << ")"); + } + + // password + string password; + ConstElementPtr password_cfg = client->get("password"); + if (password_cfg) { + if (password_cfg->getType() != Element::string) { + isc_throw(DhcpConfigError, "password must be a string (" + << password_cfg->getPosition() << ")"); + } + password = password_cfg->stringValue(); + } + + // user context + ConstElementPtr user_context = client->get("user-context"); + if (user_context) { + if (user_context->getType() != Element::map) { + isc_throw(DhcpConfigError, "user-context must be a map (" + << user_context->getPosition() << ")"); + } + } + + // add it. + try { + add(user, password, user_context); + } catch (const std::exception& ex) { + isc_throw(DhcpConfigError, ex.what() << " (" + << client->getPosition() << ")"); + } + } +} + +} // end of namespace isc::http +} // end of namespace isc diff --git a/src/lib/http/basic_auth_config.h b/src/lib/http/basic_auth_config.h new file mode 100644 index 0000000000..a5d3e74a6c --- /dev/null +++ b/src/lib/http/basic_auth_config.h @@ -0,0 +1,120 @@ +// Copyright (C) 2020 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef HTTP_BASIC_AUTH_CONFIG_H +#define HTTP_BASIC_AUTH_CONFIG_H + +#include +#include +#include +#include +#include +#include +#include + +namespace isc { +namespace http { + +/// @brief Type of basic HTTP authentication credential and user id map. +typedef std::unordered_map BasicHttpAuthMap; + +/// @brief Basic HTTP authentication client configuration. +class BasicHttpAuthClient : public isc::data::UserContext, + public isc::data::CfgToElement { +public: + + /// @brief Constructor. + /// + /// @param user User id + /// @param password Password + /// @param user_context Optional user context + BasicHttpAuthClient(const std::string& user, + const std::string& password, + const isc::data::ConstElementPtr& user_context); + + /// @brief Returns the user id. + const std::string& getUser() const { + return (user_); + } + + /// @brief Returns the password. + const std::string& getPassword() const { + return (password_); + } + + /// @brief Unparses basic HTTP authentication client configuration. + /// + /// @return A pointer to unparsed client configuration. + virtual isc::data::ElementPtr toElement() const; + +private: + + /// @brief The user id. + std::string user_; + + /// @brief The password. + std::string password_; +}; + +/// @brief Type of basic HTTP authentication client configuration list. +typedef std::list BasicHttpAuthClientList; + +/// @brief Basic HTTP authentication configuration. +class BasicHttpAuthConfig : public isc::data::CfgToElement { +public: + + /// @brief Add a client configuration. + /// + /// @param user User id + /// @param password Password + /// @param user_context Optional user context + /// @throw BadValue if the user id contains the ':' character. + void add(const std::string& user, + const std::string& password, + const isc::data::ConstElementPtr& user_context = isc::data::ConstElementPtr()); + + /// @brief Clear configuration. + void clear(); + + /// @brief Returns the list of client configuration. + /// + /// @return List of basic HTTP authentication client configuration. + const BasicHttpAuthClientList& getClientList() const { + return (list_); + } + + /// @brief Returns the credential and user id map. + /// + /// @return The basic HTTP authentication credential and user id map. + const BasicHttpAuthMap& getCredentialMap() const { + return (map_); + } + + /// @brief Parses basic HTTP authentication configuration. + /// + /// @param config Element holding the basic HTTP authentication + /// configuration to be parsed. + /// @throw DhcpConfigError when the configuration is invalid. + void parse(const isc::data::ConstElementPtr& config); + + /// @brief Unparses basic HTTP authentication configuration. + /// + /// @return A pointer to unparsed basic HTTP authentication configuration. + virtual isc::data::ElementPtr toElement() const; + +private: + + /// @brief The list of basic HTTP authentication client configuration. + BasicHttpAuthClientList list_; + + /// @brief The basic HTTP authentication credential and user id map. + BasicHttpAuthMap map_; +}; + +} // end of namespace isc::http +} // end of namespace isc + +#endif // endif HTTP_BASIC_AUTH_CONFIG_H diff --git a/src/lib/http/response_creator_auth.h b/src/lib/http/response_creator_auth.h index 5cc085d071..0bcfe2c993 100644 --- a/src/lib/http/response_creator_auth.h +++ b/src/lib/http/response_creator_auth.h @@ -7,6 +7,7 @@ #ifndef HTTP_RESPONSE_CREATOR_AUTH_H #define HTTP_RESPONSE_CREATOR_AUTH_H +#include #include #include #include @@ -14,9 +15,6 @@ namespace isc { namespace http { -/// @brief Type of basic HTTP authentication credential and user id map. -typedef std::unordered_map BasicHttpAuthMap; - /// @brief Validate basic HTTP authentication. /// /// @param creator The HTTP response creator. diff --git a/src/lib/http/tests/Makefile.am b/src/lib/http/tests/Makefile.am index e88d4dcccc..6dd63a1d5e 100644 --- a/src/lib/http/tests/Makefile.am +++ b/src/lib/http/tests/Makefile.am @@ -21,6 +21,7 @@ if HAVE_GTEST TESTS += libhttp_unittests libhttp_unittests_SOURCES = basic_auth_unittests.cc +libhttp_unittests_SOURCES += basic_auth_config_unittests.cc libhttp_unittests_SOURCES += connection_pool_unittests.cc libhttp_unittests_SOURCES += date_time_unittests.cc libhttp_unittests_SOURCES += http_header_unittests.cc diff --git a/src/lib/http/tests/basic_auth_config_unittests.cc b/src/lib/http/tests/basic_auth_config_unittests.cc new file mode 100644 index 0000000000..5b7cd8605f --- /dev/null +++ b/src/lib/http/tests/basic_auth_config_unittests.cc @@ -0,0 +1,218 @@ +// Copyright (C) 2020 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#include +#include +#include +#include +#include + +using namespace isc; +using namespace isc::data; +using namespace isc::dhcp; +using namespace isc::http; +using namespace isc::test; +using namespace std; + +namespace { + +// Test that basic auth client works as expected. +TEST(BasicHttpAuthClientTest, basic) { + // Create a client. + ConstElementPtr ctx = Element::fromJSON("{ \"foo\": \"bar\" }"); + BasicHttpAuthClient client("foo", "bar", ctx); + + // Check it. + EXPECT_EQ("foo", client.getUser()); + EXPECT_EQ("bar", client.getPassword()); + EXPECT_TRUE(ctx->equals(*client.getContext())); + + // Check toElement. + ElementPtr expected = Element::createMap(); + expected->set("user", Element::create(string("foo"))); + expected->set("password", Element::create(string("bar"))); + expected->set("user-context", ctx); + runToElementTest(expected, client); +} + +// Test that basic auth configuration works as expected. +TEST(BasicHttpAuthConfigTest, basic) { + // Create a configuration. + BasicHttpAuthConfig config; + + // Initial configuration is empty. + EXPECT_TRUE(config.getClientList().empty()); + EXPECT_TRUE(config.getCredentialMap().empty()); + + // Add rejects user id with embedded ':'. + EXPECT_THROW(config.add("foo:", "bar"), BadValue); + + // Add a client. + ConstElementPtr ctx = Element::fromJSON("{ \"foo\": \"bar\" }"); + EXPECT_NO_THROW(config.add("foo", "bar", ctx)); + + // Check the client. + ASSERT_EQ(1, config.getClientList().size()); + const BasicHttpAuthClient& client = config.getClientList().front(); + EXPECT_EQ("foo", client.getUser()); + EXPECT_EQ("bar", client.getPassword()); + EXPECT_TRUE(ctx->equals(*client.getContext())); + + // Check the credential. + ASSERT_NE(0, config.getCredentialMap().count("Zm9vOmJhcg==")); + string user; + EXPECT_NO_THROW(user = config.getCredentialMap().at("Zm9vOmJhcg==")); + EXPECT_EQ("foo", user); + + // Check toElement. + ElementPtr expected = Element::createList(); + ElementPtr elem = Element::createMap(); + elem->set("user", Element::create(string("foo"))); + elem->set("password", Element::create(string("bar"))); + elem->set("user-context", ctx); + expected->add(elem); + runToElementTest(expected, config); + + // Add a second client and test it. + EXPECT_NO_THROW(config.add("test", "123\xa3")); + ASSERT_EQ(2, config.getClientList().size()); + EXPECT_EQ("foo", config.getClientList().front().getUser()); + EXPECT_EQ("test", config.getClientList().back().getUser()); + ASSERT_NE(0, config.getCredentialMap().count("dGVzdDoxMjPCow==")); + + // Check clear. + config.clear(); + expected = Element::createList(); + runToElementTest(expected, config); + + // Add clients again. + EXPECT_NO_THROW(config.add("test", "123\xa3")); + EXPECT_NO_THROW(config.add("foo", "bar", ctx)); + + // Check that toElement keeps add order. + ElementPtr elem0 = Element::createMap(); + elem0->set("user", Element::create(string("test"))); + elem0->set("password", Element::create(string("123\xa3"))); + expected->add(elem0); + expected->add(elem); + runToElementTest(expected, config); +} + +// Test that basic auth configuration parses. +TEST(BasicHttpAuthConfigTest, parse) { + BasicHttpAuthConfig config; + ElementPtr cfg; + + // No config is accepted. + EXPECT_NO_THROW(config.parse(cfg)); + EXPECT_TRUE(config.getClientList().empty()); + EXPECT_TRUE(config.getCredentialMap().empty()); + runToElementTest(Element::createList(), config); + + // The config must be a list. + cfg = Element::createMap(); + EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError, + "basic-authentications must be a list (:0:0)"); + + // The client config must be a map. + cfg = Element::createList(); + ElementPtr client_cfg = Element::createList(); + cfg->add(client_cfg); + EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError, + "basic-authentications items must be maps (:0:0)"); + + // The user parameter is mandatory in client config. + client_cfg = Element::createMap(); + cfg = Element::createList(); + cfg->add(client_cfg); + EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError, + "user is required in basic-authentications items (:0:0)"); + + // The user parameter must be a string. + ElementPtr user_cfg = Element::create(1); + client_cfg = Element::createMap(); + client_cfg->set("user", user_cfg); + cfg = Element::createList(); + cfg->add(client_cfg); + EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError, + "user must be a string (:0:0)"); + + // The user parameter must not be empty. + user_cfg = Element::create(string("")); + client_cfg = Element::createMap(); + client_cfg->set("user", user_cfg); + cfg = Element::createList(); + cfg->add(client_cfg); + EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError, + "user must be not be empty (:0:0)"); + + // The user parameter must not contain ':'. + user_cfg = Element::create(string("foo:bar")); + client_cfg = Element::createMap(); + client_cfg->set("user", user_cfg); + cfg = Element::createList(); + cfg->add(client_cfg); + EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError, + "user must not contain a ':': 'foo:bar' (:0:0)"); + + // Password is not required. + user_cfg = Element::create(string("foo")); + client_cfg = Element::createMap(); + client_cfg->set("user", user_cfg); + cfg = Element::createList(); + cfg->add(client_cfg); + EXPECT_NO_THROW(config.parse(cfg)); + ASSERT_EQ(1, config.getClientList().size()); + EXPECT_EQ("", config.getClientList().front().getPassword()); + config.clear(); + + // The password parameter must be a string. + ElementPtr password_cfg = Element::create(1); + client_cfg = Element::createMap(); + client_cfg->set("user", user_cfg); + client_cfg->set("password", password_cfg); + cfg = Element::createList(); + cfg->add(client_cfg); + EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError, + "password must be a string (:0:0)"); + + // Empty password is accepted. + password_cfg = Element::create(string("")); + client_cfg = Element::createMap(); + client_cfg->set("user", user_cfg); + client_cfg->set("password", password_cfg); + cfg = Element::createList(); + cfg->add(client_cfg); + EXPECT_NO_THROW(config.parse(cfg)); + ASSERT_EQ(1, config.getClientList().size()); + EXPECT_EQ("", config.getClientList().front().getPassword()); + config.clear(); + + // User context must be a map. + password_cfg = Element::create(string("bar")); + ElementPtr ctx = Element::createList(); + client_cfg = Element::createMap(); + client_cfg->set("user", user_cfg); + client_cfg->set("password", password_cfg); + client_cfg->set("user-context", ctx); + cfg = Element::createList(); + cfg->add(client_cfg); + EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError, + "user-context must be a map (:0:0)"); + + // Check a working not empty config. + ctx = Element::fromJSON("{ \"foo\": \"bar\" }"); + client_cfg = Element::createMap(); + client_cfg->set("user", user_cfg); + client_cfg->set("password", password_cfg); + client_cfg->set("user-context", ctx); + cfg = Element::createList(); + cfg->add(client_cfg); + EXPECT_NO_THROW(config.parse(cfg)); + runToElementTest(cfg, config); +} + +} // end of anonymous namespace -- GitLab From 86329779d08002449549756d2302143021b9a049 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Sun, 12 Jul 2020 17:32:39 +0200 Subject: [PATCH 10/33] [#1304] Checkpoint: CA to finish --- src/bin/agent/ca_cfg_mgr.cc | 16 ++- src/bin/agent/ca_cfg_mgr.h | 20 +++ src/bin/agent/ca_response_creator.cc | 43 +++++- src/bin/agent/simple_parser.cc | 5 +- src/bin/agent/tests/ca_cfg_mgr_unittests.cc | 123 +++++++++++++++++- src/bin/agent/tests/get_config_unittest.cc | 2 +- src/bin/agent/tests/testdata/get_config.json | 10 ++ src/lib/http/response_creator_auth.cc | 14 +- src/lib/http/response_creator_auth.h | 9 +- .../http/tests/response_creator_unittests.cc | 10 +- 10 files changed, 220 insertions(+), 32 deletions(-) diff --git a/src/bin/agent/ca_cfg_mgr.cc b/src/bin/agent/ca_cfg_mgr.cc index fc013113ad..6cf058357b 100644 --- a/src/bin/agent/ca_cfg_mgr.cc +++ b/src/bin/agent/ca_cfg_mgr.cc @@ -27,7 +27,9 @@ CtrlAgentCfgContext::CtrlAgentCfgContext() CtrlAgentCfgContext::CtrlAgentCfgContext(const CtrlAgentCfgContext& orig) : ConfigBase(), ctrl_sockets_(orig.ctrl_sockets_), http_host_(orig.http_host_), http_port_(orig.http_port_), - hooks_config_(orig.hooks_config_) { + basic_auth_realm_(orig.basic_auth_realm_), + hooks_config_(orig.hooks_config_), + basic_auth_config_(orig.basic_auth_config_) { } CtrlAgentCfgMgr::CtrlAgentCfgMgr() @@ -50,7 +52,11 @@ CtrlAgentCfgMgr::getConfigSummary(const uint32_t /*selection*/) { // Then print the control-sockets s << ctx->getControlSocketInfoSummary(); - // @todo: add something if authentication is required + // Add something if authentication is required. + const isc::http::BasicHttpAuthConfig& auth = ctx->getBasicAuthConfig(); + if (!auth.getClientList().empty()) { + s << ", requires basic HTTP authentication"; + } // Finally, print the hook libraries names const isc::hooks::HookLibsCollection libs = ctx->getHooksConfig().get(); @@ -165,7 +171,11 @@ CtrlAgentCfgContext::toElement() const { control_sockets->set(si->first, socket); } ca->set("control-sockets", control_sockets); - // @todo: Set authentication. + // Set basic HTTP authentication + const isc::http::BasicHttpAuthConfig& auth = basic_auth_config_; + if (!basic_auth_config_.getClientList().empty()) { + ca->set("basic-authentications", basic_auth_config_.toElement()); + } // Set Control-agent ElementPtr result = Element::createMap(); result->set("Control-agent", ca); diff --git a/src/bin/agent/ca_cfg_mgr.h b/src/bin/agent/ca_cfg_mgr.h index 74de00b277..ae39e17860 100644 --- a/src/bin/agent/ca_cfg_mgr.h +++ b/src/bin/agent/ca_cfg_mgr.h @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -126,6 +127,22 @@ public: return (hooks_config_); } + /// @brief Returns non-const reference to configured basic HTTP + /// authentification clients. + /// + /// @return non-const reference to configured basic auth clients. + isc::http::BasicHttpAuthConfig& getBasicAuthConfig() { + return (basic_auth_config_); + } + + /// @brief Returns const reference to configured basic HTTP + /// authentification clients. + /// + /// @return const reference to configured basic auth clients. + const isc::http::BasicHttpAuthConfig& getBasicAuthConfig() const { + return (basic_auth_config_); + } + /// @brief Unparse a configuration object /// /// Returns an element which must parse into the same object, i.e. @@ -166,6 +183,9 @@ private: /// @brief Configured hooks libraries. isc::hooks::HooksConfig hooks_config_; + + /// @brief Configured basic HTTP authentification clients. + isc::http::BasicHttpAuthConfig basic_auth_config_; }; /// @brief Ctrl Agent Configuration Manager. diff --git a/src/bin/agent/ca_response_creator.cc b/src/bin/agent/ca_response_creator.cc index a6ccb525e6..5995ee5fc1 100644 --- a/src/bin/agent/ca_response_creator.cc +++ b/src/bin/agent/ca_response_creator.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2017-2018 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2017-2020 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -6,10 +6,14 @@ #include +#include #include +#include +#include #include #include #include +#include #include #include #include @@ -58,6 +62,39 @@ createStockHttpResponseInternal(const ConstHttpRequestPtr& request, HttpResponsePtr CtrlAgentResponseCreator:: createDynamicHttpResponse(const ConstHttpRequestPtr& request) { + // First check authentication. + HttpResponseJsonPtr http_response; + + // Context will hold the server configuration. + CtrlAgentCfgContextPtr ctx; + + // There is a hierarchy of the objects through which we need to pass to get + // the configuration context. We may simplify this at some point but since + // we're in the singleton we want to make sure that we're using most current + // configuration. + boost::shared_ptr controller = + boost::dynamic_pointer_cast(CtrlAgentController::instance()); + if (controller) { + CtrlAgentProcessPtr process = controller->getCtrlAgentProcess(); + if (process) { + CtrlAgentCfgMgrPtr cfgmgr = process->getCtrlAgentCfgMgr(); + if (cfgmgr) { + ctx = cfgmgr->getCtrlAgentCfgContext(); + if (ctx) { + const BasicHttpAuthConfig& auth = ctx->getBasicAuthConfig(); + http_response = + checkBasicHttpAuth(*this, request, + auth.getCredentialMap(), + ctx->getBasicAuthRealm()); + } + } + } + } + // The basic HTTP authentication check failed and left a response. + if (http_response) { + return (http_response); + } + // The request is always non-null, because this is verified by the // createHttpResponse method. Let's try to convert it to the // ConstPostHttpRequestJson type as this is the type generated by the @@ -84,7 +121,7 @@ createDynamicHttpResponse(const ConstHttpRequestPtr& request) { return (createStockHttpResponse(request, HttpStatusCode::INTERNAL_SERVER_ERROR)); } // The response is ok, so let's create new HTTP response with the status OK. - HttpResponseJsonPtr http_response = boost::dynamic_pointer_cast< + http_response = boost::dynamic_pointer_cast< HttpResponseJson>(createStockHttpResponseInternal(request, HttpStatusCode::OK)); http_response->setBodyAsJson(response); http_response->finalize(); @@ -92,7 +129,5 @@ createDynamicHttpResponse(const ConstHttpRequestPtr& request) { return (http_response); } - - } // end of namespace isc::agent } // end of namespace isc diff --git a/src/bin/agent/simple_parser.cc b/src/bin/agent/simple_parser.cc index 14062dc589..f347ea40f9 100644 --- a/src/bin/agent/simple_parser.cc +++ b/src/bin/agent/simple_parser.cc @@ -90,7 +90,7 @@ AgentSimpleParser::parse(const CtrlAgentCfgContextPtr& ctx, ctx->setHttpHost(SimpleParser::getString(config, "http-host")); ctx->setHttpPort(SimpleParser::getIntType(config, "http-port")); ctx->setBasicAuthRealm(SimpleParser::getString(config, - "basic-authentication-realm")); + "basic-authentication-realm")); // Control sockets are second. ConstElementPtr ctrl_sockets = config->get("control-sockets"); @@ -102,6 +102,9 @@ AgentSimpleParser::parse(const CtrlAgentCfgContextPtr& ctx, } // Basic HTTP authentications are third. + ConstElementPtr auth_config = config->get("basic-authentications"); + ctx->getBasicAuthConfig().clear(); + ctx->getBasicAuthConfig().parse(auth_config); // User context can be done at anytime. ConstElementPtr user_context = config->get("user-context"); diff --git a/src/bin/agent/tests/ca_cfg_mgr_unittests.cc b/src/bin/agent/tests/ca_cfg_mgr_unittests.cc index f49035b31e..a77b0012a3 100644 --- a/src/bin/agent/tests/ca_cfg_mgr_unittests.cc +++ b/src/bin/agent/tests/ca_cfg_mgr_unittests.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2016-2018 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2016-2020 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -17,6 +17,7 @@ using namespace isc::agent; using namespace isc::data; using namespace isc::hooks; +using namespace isc::http; using namespace isc::process; namespace { @@ -62,6 +63,9 @@ TEST(CtrlAgentCfgMgr, contextHttpParams) { ctx.setHttpHost("alnitak"); EXPECT_EQ("alnitak", ctx.getHttpHost()); + + ctx.setBasicAuthRealm("foobar"); + EXPECT_EQ("foobar", ctx.getBasicAuthRealm()); } // Tests if context can store and retrieve control socket information. @@ -122,12 +126,16 @@ TEST(CtrlAgentCfgMgr, contextSocketInfoCopy) { EXPECT_NO_THROW(ctx.setHttpPort(12345)); EXPECT_NO_THROW(ctx.setHttpHost("bellatrix")); + EXPECT_NO_THROW(ctx.setBasicAuthRealm("foobar")); HooksConfig& libs = ctx.getHooksConfig(); string exp_name("testlib1.so"); ConstElementPtr exp_param(new StringElement("myparam")); libs.add(exp_name, exp_param); + BasicHttpAuthConfig& auth = ctx.getBasicAuthConfig(); + auth.add("foo", "bar"); + // Make a copy. ConfigPtr copy_base(ctx.clone()); CtrlAgentCfgContextPtr copy = boost::dynamic_pointer_cast(copy_base); @@ -136,6 +144,7 @@ TEST(CtrlAgentCfgMgr, contextSocketInfoCopy) { // Now check the values returned EXPECT_EQ(12345, copy->getHttpPort()); EXPECT_EQ("bellatrix", copy->getHttpHost()); + EXPECT_EQ("foobar", copy->getBasicAuthRealm()); // Check socket info ASSERT_TRUE(copy->getControlSocketInfo("d2")); @@ -151,6 +160,10 @@ TEST(CtrlAgentCfgMgr, contextSocketInfoCopy) { EXPECT_EQ(exp_name, libs2[0].first); ASSERT_TRUE(libs2[0].second); EXPECT_EQ(exp_param->str(), libs2[0].second->str()); + + // Check basic HTTP authentication + const BasicHttpAuthConfig& auth2 = copy->getBasicAuthConfig(); + EXPECT_EQ(auth.toElement()->str(), auth2.toElement()->str()); } @@ -173,6 +186,23 @@ TEST(CtrlAgentCfgMgr, contextHookParams) { EXPECT_EQ(libs.get(), stored_libs.get()); } +// Test if the context can store and retrieve basic HTTP authentication clients. +TEST(CtrlAgentCfgMgr, contextBasicAuth) { + CtrlAgentCfgContext ctx; + + // By default there should be no authentication. + BasicHttpAuthConfig& auth = ctx.getBasicAuthConfig(); + EXPECT_TRUE(auth.getClientList().empty()); + + auth.add("foo", "bar"); + auth.add("test", "123\xa3"); + + const BasicHttpAuthConfig& stored_auth = ctx.getBasicAuthConfig(); + EXPECT_EQ(2, stored_auth.getClientList().size()); + + EXPECT_EQ(auth.toElement()->str(), stored_auth.toElement()->str()); +} + /// Control Agent configurations used in tests. const char* AGENT_CONFIGS[] = { @@ -180,14 +210,16 @@ const char* AGENT_CONFIGS[] = { "{ }", // Configuration 1: http parameters only (no control sockets, not hooks) - "{ \"http-host\": \"betelgeuse\",\n" - " \"http-port\": 8001\n" + "{ \"http-host\": \"betelgeuse\",\n" + " \"http-port\": 8001,\n" + " \"basic-authentication-realm\": \"foobar\"\n" "}", // Configuration 2: http and 1 socket "{\n" " \"http-host\": \"betelgeuse\",\n" " \"http-port\": 8001,\n" + " \"basic-authentication-realm\": \"foobar\",\n" " \"control-sockets\": {\n" " \"dhcp4\": {\n" " \"socket-name\": \"/tmp/socket-v4\"\n" @@ -199,6 +231,7 @@ const char* AGENT_CONFIGS[] = { "{\n" " \"http-host\": \"betelgeuse\",\n" " \"http-port\": 8001,\n" + " \"basic-authentication-realm\": \"foobar\",\n" " \"control-sockets\": {\n" " \"dhcp4\": {\n" " \"socket-name\": \"/tmp/socket-v4\"\n" @@ -218,6 +251,7 @@ const char* AGENT_CONFIGS[] = { "{\n" " \"http-host\": \"betelgeuse\",\n" " \"http-port\": 8001,\n" + " \"basic-authentication-realm\": \"foobar\",\n" " \"control-sockets\": {\n" " \"dhcp4\": {\n" " \"socket-name\": \"/tmp/socket-v4\"\n" @@ -237,6 +271,7 @@ const char* AGENT_CONFIGS[] = { "{\n" " \"http-host\": \"betelgeuse\",\n" " \"http-port\": 8001,\n" + " \"basic-authentication-realm\": \"foobar\",\n" " \"control-sockets\": {\n" " \"d2\": {\n" " \"socket-name\": \"/tmp/socket-d2\"\n" @@ -248,6 +283,7 @@ const char* AGENT_CONFIGS[] = { "{\n" " \"http-host\": \"betelgeuse\",\n" " \"http-port\": 8001,\n" + " \"basic-authentication-realm\": \"foobar\",\n" " \"control-sockets\": {\n" " \"dhcp6\": {\n" " \"socket-name\": \"/tmp/socket-v6\"\n" @@ -255,11 +291,33 @@ const char* AGENT_CONFIGS[] = { " }\n" "}", - // Configuration 7: http and 2 sockets with user contexts and comments + // Configuration 7: http, 1 socket and basic authentication + "{\n" + " \"http-host\": \"betelgeuse\",\n" + " \"http-port\": 8001,\n" + " \"basic-authentication-realm\": \"foobar\",\n" + " \"control-sockets\": {\n" + " \"dhcp4\": {\n" + " \"socket-name\": \"/tmp/socket-v4\"\n" + " }\n" + " },\n" + " \"basic-authentications\": [" + " {" + " \"user\": \"foo\",\n" + " \"password\": \"bar\"\n" + " },{\n" + " \"user\": \"test\",\n" + " \"password\": \"123\\u00a3\"\n" + " }\n" + " ]\n" + "}", + + // Configuration 8: http and 2 sockets with user contexts and comments "{\n" " \"user-context\": { \"comment\": \"Indirect comment\" },\n" " \"http-host\": \"betelgeuse\",\n" " \"http-port\": 8001,\n" + " \"basic-authentication-realm\": \"foobar\",\n" " \"control-sockets\": {\n" " \"dhcp4\": {\n" " \"comment\": \"dhcp4 socket\",\n" @@ -269,7 +327,17 @@ const char* AGENT_CONFIGS[] = { " \"socket-name\": \"/tmp/socket-v6\",\n" " \"user-context\": { \"version\": 1 }\n" " }\n" - " }\n" + " },\n" + " \"basic-authentications\": [" + " {" + " \"comment\": \"foo is authorized\",\n" + " \"user\": \"foo\",\n" + " \"password\": \"bar\"\n" + " },{\n" + " \"user\": \"test\",\n" + " \"user-context\": { \"no password\": true }\n" + " }\n" + " ]\n" "}" }; @@ -321,6 +389,7 @@ TEST_F(AgentParserTest, configParseHttpOnly) { ASSERT_TRUE(ctx); EXPECT_EQ("betelgeuse", ctx->getHttpHost()); EXPECT_EQ(8001, ctx->getHttpPort()); + EXPECT_EQ("foobar", ctx->getBasicAuthRealm()); } // Tests if a single socket can be configured. BTW this test also checks @@ -411,9 +480,32 @@ TEST_F(AgentParserTest, configParseHooks) { EXPECT_EQ("{ \"param1\": \"foo\" }", libs[0].second->str()); } +// This test checks that the config file with basic HTTP authentication can be +// loaded. +TEST_F(AgentParserTest, configParseBasicAuth) { + configParse(AGENT_CONFIGS[7], 0); + CtrlAgentCfgContextPtr ctx = cfg_mgr_.getCtrlAgentCfgContext(); + const BasicHttpAuthConfig& auth = ctx->getBasicAuthConfig(); + + // Check credentails + auto credentials = auth.getCredentialMap(); + EXPECT_EQ(2, credentials.size()); + std::string user; + EXPECT_NO_THROW(user = credentials.at("Zm9vOmJhcg==")); + EXPECT_EQ("foo", user); + EXPECT_NO_THROW(user = credentials.at("dGVzdDoxMjPCow==")); + EXPECT_EQ("test", user); + + // Check clients. + BasicHttpAuthConfig expected; + expected.add("foo", "bar"); + expected.add("test", "123\xa3"); + EXPECT_EQ(expected.toElement()->str(), auth.toElement()->str()); +} + // This test checks comments. TEST_F(AgentParserTest, comments) { - configParse(AGENT_CONFIGS[7], 0); + configParse(AGENT_CONFIGS[8], 0); CtrlAgentCfgContextPtr agent_ctx = cfg_mgr_.getCtrlAgentCfgContext(); ASSERT_TRUE(agent_ctx); @@ -445,6 +537,23 @@ TEST_F(AgentParserTest, comments) { ASSERT_EQ(1, ctx6->size()); ASSERT_TRUE(ctx6->get("version")); EXPECT_EQ("1", ctx6->get("version")->str()); + + // Check basic HTTP authentication comment. + const BasicHttpAuthConfig& auth = agent_ctx->getBasicAuthConfig(); + auto clients = auth.getClientList(); + ASSERT_EQ(2, clients.size()); + ConstElementPtr ctx7 = clients.front().getContext(); + ASSERT_TRUE(ctx7); + ASSERT_EQ(1, ctx7->size()); + ASSERT_TRUE(ctx7->get("comment")); + EXPECT_EQ("\"foo is authorized\"", ctx7->get("comment")->str()); + + // Check basic HTTP authentication user context. + ConstElementPtr ctx8 = clients.back().getContext(); + ASSERT_TRUE(ctx8); + ASSERT_EQ(1, ctx8->size()); + ASSERT_TRUE(ctx8->get("no password")); + EXPECT_EQ("true", ctx8->get("no password")->str()); } -}; // end of anonymous namespace +} // end of anonymous namespace diff --git a/src/bin/agent/tests/get_config_unittest.cc b/src/bin/agent/tests/get_config_unittest.cc index aff503bea6..b028ea8199 100644 --- a/src/bin/agent/tests/get_config_unittest.cc +++ b/src/bin/agent/tests/get_config_unittest.cc @@ -1,4 +1,4 @@ -// Copyright (C) 2017-2018 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2017-2020 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/src/bin/agent/tests/testdata/get_config.json b/src/bin/agent/tests/testdata/get_config.json index 725b84337a..db6515f03c 100644 --- a/src/bin/agent/tests/testdata/get_config.json +++ b/src/bin/agent/tests/testdata/get_config.json @@ -1,5 +1,15 @@ { "Control-agent": { + "basic-authentication-realm": "kea-control-agent", + "basic-authentications": [ + { + "password": "1234", + "user": "admin", + "user-context": { + "comment": "admin is authorized" + } + } + ], "control-sockets": { "d2": { "socket-name": "/tmp/kea-ddns-ctrl-socket", diff --git a/src/lib/http/response_creator_auth.cc b/src/lib/http/response_creator_auth.cc index 21c13ee028..3b278ddb04 100644 --- a/src/lib/http/response_creator_auth.cc +++ b/src/lib/http/response_creator_auth.cc @@ -17,10 +17,10 @@ using namespace std; namespace isc { namespace http { -HttpResponsePtr checkBasicHttpAuth(HttpResponseCreatorPtr creator, - const ConstHttpRequestPtr& request, - const BasicHttpAuthMap& credentials, - const std::string& realm) { +HttpResponseJsonPtr checkBasicHttpAuth(const HttpResponseCreator& creator, + const ConstHttpRequestPtr& request, + const BasicHttpAuthMap& credentials, + const std::string& realm) { try { string value = request->getHeaderValue("Authorization"); // Trim space characters. @@ -43,7 +43,7 @@ HttpResponsePtr checkBasicHttpAuth(HttpResponseCreatorPtr creator, LOG_DEBUG(http_logger, isc::log::DBGLVL_TRACE_BASIC, HTTP_CLIENT_REQUEST_AUTHORIZED) .arg(it->second); - return (HttpResponsePtr()); + return (HttpResponseJsonPtr()); } LOG_INFO(http_logger, HTTP_CLIENT_REQUEST_NOT_AUTHORIZED); } catch (const HttpMessageNonExistingHeader&) { @@ -53,13 +53,13 @@ HttpResponsePtr checkBasicHttpAuth(HttpResponseCreatorPtr creator, .arg(ex.what()); } HttpResponsePtr response = - creator->createStockHttpResponse(request, HttpStatusCode::UNAUTHORIZED); + creator.createStockHttpResponse(request, HttpStatusCode::UNAUTHORIZED); response->reset(); response->context()->headers_.push_back( HttpHeaderContext("WWW-Authenticate", "Basic realm=\"" + realm + "\"")); response->finalize(); - return (response); + return (boost::dynamic_pointer_cast(response)); } } // end of namespace isc::http diff --git a/src/lib/http/response_creator_auth.h b/src/lib/http/response_creator_auth.h index 0bcfe2c993..1b5462dbe3 100644 --- a/src/lib/http/response_creator_auth.h +++ b/src/lib/http/response_creator_auth.h @@ -9,6 +9,7 @@ #include #include +#include #include #include @@ -22,10 +23,10 @@ namespace http { /// @param credentials Authorized credentials and user id map. /// @param realm Realm name. /// @return Error HTTP response if validation failed, null otherwise. -HttpResponsePtr checkBasicHttpAuth(HttpResponseCreatorPtr creator, - const ConstHttpRequestPtr& request, - const BasicHttpAuthMap& credentials, - const std::string& realm); +HttpResponseJsonPtr checkBasicHttpAuth(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 5c65649a52..e32f60dcbd 100644 --- a/src/lib/http/tests/response_creator_unittests.cc +++ b/src/lib/http/tests/response_creator_unittests.cc @@ -151,7 +151,7 @@ TEST_F(HttpResponseCreatorAuthTest, noAuth) { string realm = "ISC.ORG"; ASSERT_NO_THROW(response = - checkBasicHttpAuth(creator, request, credentials, realm)); + checkBasicHttpAuth(*creator, request, credentials, realm)); ASSERT_TRUE(response); EXPECT_EQ("HTTP/1.0 401 Unauthorized\r\n" @@ -185,7 +185,7 @@ TEST_F(HttpResponseCreatorAuthTest, authTooShort) { string realm = "ISC.ORG"; ASSERT_NO_THROW(response = - checkBasicHttpAuth(creator, request, credentials, realm)); + checkBasicHttpAuth(*creator, request, credentials, realm)); ASSERT_TRUE(response); EXPECT_EQ("HTTP/1.0 401 Unauthorized\r\n" @@ -220,7 +220,7 @@ TEST_F(HttpResponseCreatorAuthTest, badScheme) { string realm = "ISC.ORG"; ASSERT_NO_THROW(response = - checkBasicHttpAuth(creator, request, credentials, realm)); + checkBasicHttpAuth(*creator, request, credentials, realm)); ASSERT_TRUE(response); EXPECT_EQ("HTTP/1.0 401 Unauthorized\r\n" @@ -255,7 +255,7 @@ TEST_F(HttpResponseCreatorAuthTest, notMatching) { string realm = "ISC.ORG"; ASSERT_NO_THROW(response = - checkBasicHttpAuth(creator, request, credentials, realm)); + checkBasicHttpAuth(*creator, request, credentials, realm)); ASSERT_TRUE(response); EXPECT_EQ("HTTP/1.0 401 Unauthorized\r\n" @@ -293,7 +293,7 @@ TEST_F(HttpResponseCreatorAuthTest, matching) { string realm = "ISC.ORG"; ASSERT_NO_THROW(response = - checkBasicHttpAuth(creator, request, credentials, realm)); + checkBasicHttpAuth(*creator, request, credentials, realm)); EXPECT_FALSE(response); addString("HTTP_CLIENT_REQUEST_AUTHORIZED received HTTP request " -- GitLab From 59159be343dca945b832742ab3940bb98bb26510 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Mon, 13 Jul 2020 09:31:02 +0200 Subject: [PATCH 11/33] [#1304] Added CA test --- src/bin/agent/ca_response_creator.cc | 11 +- .../tests/ca_response_creator_unittests.cc | 109 +++++++++++++++++- 2 files changed, 113 insertions(+), 7 deletions(-) diff --git a/src/bin/agent/ca_response_creator.cc b/src/bin/agent/ca_response_creator.cc index 5995ee5fc1..c102157f21 100644 --- a/src/bin/agent/ca_response_creator.cc +++ b/src/bin/agent/ca_response_creator.cc @@ -82,10 +82,13 @@ createDynamicHttpResponse(const ConstHttpRequestPtr& request) { ctx = cfgmgr->getCtrlAgentCfgContext(); if (ctx) { const BasicHttpAuthConfig& auth = ctx->getBasicAuthConfig(); - http_response = - checkBasicHttpAuth(*this, request, - auth.getCredentialMap(), - ctx->getBasicAuthRealm()); + const BasicHttpAuthMap& auth_map = auth.getCredentialMap(); + // Check authentication when required. + if (!auth_map.empty()) { + http_response = + checkBasicHttpAuth(*this, request, auth_map, + ctx->getBasicAuthRealm()); + } } } } diff --git a/src/bin/agent/tests/ca_response_creator_unittests.cc b/src/bin/agent/tests/ca_response_creator_unittests.cc index 2af027f964..35028cdb4a 100644 --- a/src/bin/agent/tests/ca_response_creator_unittests.cc +++ b/src/bin/agent/tests/ca_response_creator_unittests.cc @@ -5,26 +5,31 @@ // file, You can obtain one at http://mozilla.org/MPL/2.0/. #include +#include +#include #include #include #include #include #include #include +#include #include #include #include +using namespace isc; using namespace isc::agent; using namespace isc::config; using namespace isc::data; using namespace isc::http; +using namespace isc::process; namespace ph = std::placeholders; namespace { /// @brief Test fixture class for @ref CtrlAgentResponseCreator. -class CtrlAgentResponseCreatorTest : public ::testing::Test { +class CtrlAgentResponseCreatorTest : public DControllerTest { public: /// @brief Constructor. @@ -33,7 +38,8 @@ public: /// create "empty" request. It also removes registered commands from the /// command manager. CtrlAgentResponseCreatorTest() - : response_creator_(), + : DControllerTest(CtrlAgentController::instance), + response_creator_(), request_(response_creator_.createNewHttpRequest()) { // Deregisters commands. CtrlAgentCommandMgr::instance().deregisterAll(); @@ -47,6 +53,13 @@ public: ADD_FAILURE() << "CtrlAgentResponseCreator::createNewHttpRequest" " returns NULL!"; } + // Initialize process and cfgmgr. + try { + initProcess(); + static_cast(getCtrlAgentCfgContext()); + } catch (const std::exception& ex) { + ADD_FAILURE() << "Initialization failed: " << ex.what(); + } } /// @brief Destructor. @@ -112,6 +125,24 @@ public: return (createAnswer(CONTROL_RESULT_SUCCESS, arguments)); } + /// @brief Returns a pointer to the configuration context. + CtrlAgentCfgContextPtr getCtrlAgentCfgContext() { + CtrlAgentProcessPtr process = + boost::dynamic_pointer_cast(getProcess()); + if (!process) { + isc_throw(Unexpected, "no process"); + } + CtrlAgentCfgMgrPtr cfgmgr = process->getCtrlAgentCfgMgr(); + if (!cfgmgr) { + isc_throw(Unexpected, "no cfgmgr"); + } + CtrlAgentCfgContextPtr ctx = cfgmgr->getCtrlAgentCfgContext(); + if (!ctx) { + isc_throw(Unexpected, "no context"); + } + return (ctx); + } + /// @brief Instance of the response creator. CtrlAgentResponseCreator response_creator_; @@ -120,7 +151,6 @@ public: /// The context belonging to this request may be modified by the unit /// tests to verify various scenarios of response creation. HttpRequestPtr request_; - }; // This test verifies that the created "empty" request has valid type. @@ -204,7 +234,80 @@ TEST_F(CtrlAgentResponseCreatorTest, createDynamicHttpResponseInvalidType) { // Response must contain Internal Server Error status code. EXPECT_TRUE(response_json->toString().find("HTTP/1.1 500 Internal Server Error") != std::string::npos); +} + +// This test verifies that Unauthorized is returned when authentication is +// required but not provided by request. +TEST_F(CtrlAgentResponseCreatorTest, noAuth) { + setBasicContext(request_); + + // Body: "list-commands" is natively supported by the command manager. + request_->context()->body_ = "{ \"command\": \"list-commands\" }"; + + // All requests must be finalized before they can be processed. + ASSERT_NO_THROW(request_->finalize()); + + // Require authentication. + CtrlAgentCfgContextPtr ctx = getCtrlAgentCfgContext(); + ASSERT_TRUE(ctx); + ctx->setBasicAuthRealm("ISC.ORG"); + BasicHttpAuthConfig& auth = ctx->getBasicAuthConfig(); + auth.add("foo", "bar"); + + HttpResponsePtr response; + ASSERT_NO_THROW(response = response_creator_.createHttpResponse(request_)); + ASSERT_TRUE(response); + // Response must be convertible to HttpResponseJsonPtr. + HttpResponseJsonPtr response_json = boost::dynamic_pointer_cast< + HttpResponseJson>(response); + ASSERT_TRUE(response_json); + + // Response must contain Unauthorized status code. + std::string expected = "HTTP/1.1 401 Unauthorized"; + EXPECT_TRUE(response_json->toString().find(expected) != std::string::npos); + // Reponse should contain WWW-Authenticate header with configured realm. + expected = "WWW-Authenticate: Basic realm=\"ISC.ORG\""; + EXPECT_TRUE(response_json->toString().find(expected) != std::string::npos); +} + +// Test successful server response when the client is authenticated. +TEST_F(CtrlAgentResponseCreatorTest, basicAuth) { + setBasicContext(request_); + + // Body: "list-commands" is natively supported by the command manager. + request_->context()->body_ = "{ \"command\": \"list-commands\" }"; + + // Add basic HTTP authentication header. + const BasicHttpAuth& basic_auth = BasicHttpAuth("foo", "bar"); + const BasicAuthHttpHeaderContext& basic_auth_header = + BasicAuthHttpHeaderContext(basic_auth); + request_->context()->headers_.push_back(basic_auth_header); + + // All requests must be finalized before they can be processed. + ASSERT_NO_THROW(request_->finalize()); + + // Require authentication. + CtrlAgentCfgContextPtr ctx = getCtrlAgentCfgContext(); + ASSERT_TRUE(ctx); + BasicHttpAuthConfig& auth = ctx->getBasicAuthConfig(); + auth.add("foo", "bar"); + + HttpResponsePtr response; + ASSERT_NO_THROW(response = response_creator_.createHttpResponse(request_)); + ASSERT_TRUE(response); + + // Response must be convertible to HttpResponseJsonPtr. + HttpResponseJsonPtr response_json = boost::dynamic_pointer_cast< + HttpResponseJson>(response); + ASSERT_TRUE(response_json); + + // Response must be successful. + EXPECT_TRUE(response_json->toString().find("HTTP/1.1 200 OK") != + std::string::npos); + // Response must contain JSON body with "result" of 0. + EXPECT_TRUE(response_json->toString().find("\"result\": 0") != + std::string::npos); } } -- GitLab From ee3c8f2d1c30e33735b8876448a3a7f3d0ebb673 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Mon, 13 Jul 2020 10:14:25 +0200 Subject: [PATCH 12/33] [#1304] Updated CA doc --- doc/sphinx/arm/agent.rst | 40 +++++++++++++++++++++++++++++----- doc/sphinx/arm/shell.rst | 11 +++++++++- doc/sphinx/man/kea-shell.8.rst | 4 ++-- src/bin/shell/kea-shell.rst | 4 ++-- 4 files changed, 49 insertions(+), 10 deletions(-) diff --git a/doc/sphinx/arm/agent.rst b/doc/sphinx/arm/agent.rst index 51bd64aae0..37c215a12a 100644 --- a/doc/sphinx/arm/agent.rst +++ b/doc/sphinx/arm/agent.rst @@ -50,6 +50,7 @@ The following example demonstrates the basic CA configuration. "Control-agent": { "http-host": "10.20.30.40", "http-port": 8000, + "basic-authentication-realm": "kea-control-agent", "control-sockets": { "dhcp4": { @@ -68,6 +69,12 @@ The following example demonstrates the basic CA configuration. }, }, + "basic-authentications": [ + { + "user": "admin", + "password": "1234" + } ], + "hooks-libraries": [ { "library": "/opt/local/control-agent-commands.so", @@ -125,10 +132,32 @@ formatting; please consult the relevant hook library documentation for details. User contexts can be specified on either global scope, control socket, -or loggers. One other useful feature is the ability to store comments or -descriptions; the parser translates a "comment" entry into a user -context with the entry, which allows a comment to be attached within the -configuration itself. +basic authentication, or loggers. One other useful feature is the +ability to store comments or descriptions; the parser translates a +"comment" entry into a user context with the entry, which allows a +comment to be attached within the configuration itself. + +The basic HTTP authentication was added by Kea 1.7.10. It protects +not authorized uses of the control agent by local users. For the +protection against remote attackers HTTPS and reverse proxy of +:ref:`agent-secure-connection` provide a stronger security. + +The ``basic-authentication-realm`` is used for error message when +the basic HTTP authentication is mandatory but the client is not +authorized. + +When the ``basic-authentications`` list is configured and not empty +the basic HTTP authentication is required. Each element of the list +specifies a user id and a password. The user id is mandatory, must +be not empty and must not contain the colon (:) character. The +password is optional: when it is not specified an empty password +is used. + +.. note:: + + The basic HTTP authentication user id and password are encoded + in UTF-8 but the current Kea JSON syntax only supports the latin-1 + (i.e. 0x00..0xff) unicode subset. Hooks libraries can be loaded by the Control Agent in the same way as they are loaded by the DHCPv4 and DHCPv6 servers. The CA currently @@ -151,7 +180,7 @@ The Control Agent does not natively support secure HTTP connections like SSL or TLS. In order to setup a secure connection, please use one of the available third-party HTTP servers and configure it to run as a reverse proxy to the Control Agent. Kea has been tested with two major HTTP -server implentations working as a reverse proxy: Apache2 and nginx. +server implementations working as a reverse proxy: Apache2 and nginx. Example configurations, including extensive comments, are provided in the ``doc/examples/https/`` directory. @@ -205,6 +234,7 @@ server enables authentication of the clients using certificates. # -H Content-Type:application/json -d '{ "command": "list-commands" }' \ # https://kea.example.org/kea # + # curl syntax for basic authentication is -u user:password # # # nginx configuration starts here. diff --git a/doc/sphinx/arm/shell.rst b/doc/sphinx/arm/shell.rst index 75ba6a543d..9380a316aa 100644 --- a/doc/sphinx/arm/shell.rst +++ b/doc/sphinx/arm/shell.rst @@ -22,6 +22,8 @@ As the primary purpose of the Kea shell is as a tool in a scripting environment, it is not interactive. However, following simple guidelines it can be run manually. +Kea 1.7.10 introduced basic HTTP authentication support. + Shell Usage =========== @@ -29,7 +31,7 @@ Shell Usage .. code-block:: console - $ kea-shell [--host hostname] [--port number] [--path path] [--timeout seconds] [--service service-name] [command] + $ kea-shell [--host hostname] [--port number] [--path path] [--auth-user] [--auth-password] [--timeout seconds] [--service service-name] [command] where: @@ -43,6 +45,13 @@ where: specified, an empty path is used. As the CA listens at the empty path, this parameter is useful only with a reverse proxy. +- ``--auth-user`` specifies the user id for basic HTTP authentication. + If not specified or specified as the empty string authentication is + not used. + +- ``--auth-password`` specifies the password for basic HTTP authentication. + If not specified but the user id is specified an empty password is used. + - ``--timeout seconds`` specifies the timeout (in seconds) for the connection. If not given, 10 seconds is used. diff --git a/doc/sphinx/man/kea-shell.8.rst b/doc/sphinx/man/kea-shell.8.rst index fb88cdc419..2fe12ee410 100644 --- a/doc/sphinx/man/kea-shell.8.rst +++ b/doc/sphinx/man/kea-shell.8.rst @@ -51,12 +51,12 @@ The arguments are as follows: parameter is useful only with a reverse proxy. ``--auth-user`` - Specifies the user name for basic HTTP authentication. If not specified + Specifies the user id for basic HTTP authentication. If not specified or specified as the empty string authentication is not used. ``--auth-password`` Specifies the password for basic HTTP authentication. If not specified - but the user name is specified an empty password is used. + but the user id is specified an empty password is used. ``--timeout`` Specifies the connection timeout in seconds. If not specified, 10 diff --git a/src/bin/shell/kea-shell.rst b/src/bin/shell/kea-shell.rst index 6a721f9699..b10483f97e 100644 --- a/src/bin/shell/kea-shell.rst +++ b/src/bin/shell/kea-shell.rst @@ -50,12 +50,12 @@ The arguments are as follows: parameter is useful only with a reverse proxy. ``--auth-user`` - Specifies the user name for basic HTTP authentication. If not specified + Specifies the user id for basic HTTP authentication. If not specified or specified as the empty string authentication is not used. ``--auth-password`` Specifies the password for basic HTTP authentication. If not specified - but the user name is specified an empty password is used. + but the user id is specified an empty password is used. ``--timeout`` Specifies the connection timeout in seconds. If not specified, 10 -- GitLab From b3da31ef1bfa91be381a78fb33c9f4bc1406d602 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Mon, 13 Jul 2020 10:58:42 +0200 Subject: [PATCH 13/33] [#1304] Updated shell tests --- configure.ac | 13 +- src/bin/shell/tests/Makefile.am | 4 +- src/bin/shell/tests/basic_auth_tests.sh.in | 175 +++++++++++++++++++++ 3 files changed, 184 insertions(+), 8 deletions(-) create mode 100644 src/bin/shell/tests/basic_auth_tests.sh.in diff --git a/configure.ac b/configure.ac index 91df9a514b..abfb61ed3b 100755 --- a/configure.ac +++ b/configure.ac @@ -1521,12 +1521,12 @@ if test "x$enable_fuzzing" != "xno" ; then AC_DEFINE([ENABLE_AFL], [1], [AFL fuzzing was enabled.]) AC_MSG_CHECKING([for AFL enabled compiler]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], - [#ifndef __AFL_COMPILER - #error AFL compiler required - #endif - ])], - [AC_MSG_RESULT([yes])], - [AC_MSG_ERROR([set CXX to afl-clang-fast++ when --enable-fuzzing is used])]) + [#ifndef __AFL_COMPILER + #error AFL compiler required + #endif + ])], + [AC_MSG_RESULT([yes])], + [AC_MSG_ERROR([set CXX to afl-clang-fast++ when --enable-fuzzing is used])]) fi @@ -1625,6 +1625,7 @@ AC_CONFIG_FILES([Makefile src/bin/shell/Makefile src/bin/shell/kea-shell src/bin/shell/tests/Makefile + src/bin/shell/tests/basic_auth_tests.sh src/bin/shell/tests/shell_process_tests.sh src/bin/shell/tests/shell_unittest.py src/hooks/Makefile diff --git a/src/bin/shell/tests/Makefile.am b/src/bin/shell/tests/Makefile.am index c3e6777aac..1186885782 100644 --- a/src/bin/shell/tests/Makefile.am +++ b/src/bin/shell/tests/Makefile.am @@ -1,8 +1,8 @@ PYTESTS = shell_unittest.py -SHTESTS = shell_process_tests.sh +SHTESTS = shell_process_tests.sh basic_auth_tests.sh noinst_SCRIPTS = $(PYTESTS) $(SHTESTS) -DISTCLEANFILES = shell_process_tests.sh shell_unittest.py +DISTCLEANFILES = basic_auth_tests.sh shell_process_tests.sh shell_unittest.py # test using command-line arguments, so use check-local target instead of TESTS check-local: check-shell check-python diff --git a/src/bin/shell/tests/basic_auth_tests.sh.in b/src/bin/shell/tests/basic_auth_tests.sh.in new file mode 100644 index 0000000000..57fb3ad438 --- /dev/null +++ b/src/bin/shell/tests/basic_auth_tests.sh.in @@ -0,0 +1,175 @@ +# Copyright (C) 2020 Internet Systems Consortium, Inc. ("ISC") +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# Path to the temporary configuration file. +CFG_FILE=@abs_top_builddir@/src/bin/shell/tests/test_config.json +# Path to the Control Agent log file. +LOG_FILE=@abs_top_builddir@/src/bin/shell/tests/test.log + +# Control Agent configuration to be stored in the configuration file. +# todo: use actual configuration once we support it. +CONFIG="{ + \"Control-agent\": + { + \"http-host\": \"127.0.0.1\", + \"http-port\": 8081, + \"basic-authentication-realm\": \"ISC.ORG\", + \"basic-authentications\": [ + { + \"user\": \"pet\", + \"password\": \"meow\" + } + ], + \"loggers\": [ + { + \"name\": \"kea-ctrl-agent\", + \"output_options\": [ + { + \"output\": \"$LOG_FILE\" + } + ], + \"severity\": \"DEBUG\" + } + ] + } +}" + +# In these tests we need to use two binaries: Control Agent and Kea shell. +# Using bin and bin_path would be confusing, so we omit defining bin +# and bin_path on purpose. +ca_bin="kea-ctrl-agent" +ca_bin_path=@abs_top_builddir@/src/bin/agent + +shell_bin="kea-shell" +shell_bin_path=@abs_top_builddir@/src/bin/shell + +tmpfile_path=@abs_top_builddir@/src/bin/shell/tests + +# Import common test library. +. @abs_top_builddir@/src/lib/testutils/dhcp_test_lib.sh + +# This test verifies that Control Agent is shut down gracefully when it +# receives a SIGINT or SIGTERM signal. +shell_command_test() { + test_name=${1} # Test name + auth=${2} # Authentication + cmd=${3} # Command to be sent + exp_result=${4} # Expected result + exp_rsp=${5} # Expected response + + # Setup phase: start CA. + + # Log the start of the test and print test name. + test_start ${test_name} + + # Remove any dangling CA instances and remove log files. + cleanup + + # Create new configuration file. + create_config "${CONFIG}" + + # Instruct Control Agent to log to the specific file. + set_logger + # Start Control Agent. + start_kea ${ca_bin_path}/${ca_bin} + # Wait up to 20s for Control Agent to start. + wait_for_kea 20 + if [ ${_WAIT_FOR_KEA} -eq 0 ]; then + printf "ERROR: timeout waiting for Control Agent to start.\n" + clean_exit 1 + fi + + # Check if it is still running. It could have terminated (e.g. as a result + # of configuration failure). + get_pid ${ca_bin} + if [ ${_GET_PIDS_NUM} -ne 1 ]; then + printf "ERROR: expected one Control Agent process to be started.\ + Found %d processes started.\n" ${_GET_PIDS_NUM} + clean_exit 1 + fi + + # Check in the log file, how many times server has been configured. + # It should be just once on startup. + get_reconfigs + if [ ${_GET_RECONFIGS} -ne 1 ]; then + printf "ERROR: server been configured ${_GET_RECONFIGS} time(s),\ + but exactly 1 was expected.\n" + clean_exit 1 + else + printf "Server successfully configured.\n" + fi + + # Main test phase: send command, check response. + tmp="echo | ${shell_bin_path}/${shell_bin} --host \ + 127.0.0.1 --port 8081 ${auth} ${cmd} > ${tmpfile_path}/shell-stdout.txt" + echo "Executing kea-shell ($tmp)" + + echo | ${shell_bin_path}/${shell_bin} --host 127.0.0.1 \ + --port 8081 ${auth} ${cmd} > ${tmpfile_path}/shell-stdout.txt + + # Check the exit code + shell_exit_code=$? + if [ ${exp_result} == "fail" ]; then + if [ ${shell_exit_code} -eq 0 ]; then + echo "ERROR:" \ + "kea-shell returned ${shell_exit_code} exit code, expected 1." + else + echo "kea-shell returned ${shell_exit_code} exit code as expected." + fi + elif [ ${shell_exit_code} -ne 0 ]; then + echo "ERROR:" \ + "kea-shell returned ${shell_exit_code} exit code, expected 0." + else + echo "kea-shell returned ${shell_exit_code} exit code as expected." + fi + + # Now check the response + rm -f ${tmpfile_path}/shell-expected.txt + echo ${exp_rsp} > ${tmpfile_path}/shell-expected.txt + diff ${tmpfile_path}/shell-stdout.txt ${tmpfile_path}/shell-expected.txt + diff_code=$? + if [ ${diff_code} -ne 0 ]; then + echo "ERROR:" \ + "content returned is different than expected." \ + "See ${tmpfile_path}/shell-*.txt" + echo "EXPECTED:" + cat ${tmpfile_path}/shell-expected.txt + echo "ACTUAL RESULT:" + cat ${tmpfile_path}/shell-stdout.txt + clean_exit 1 + else + echo "Content returned by kea-shell meets expectation." + rm ${tmpfile_path}/shell-*.txt + fi + # Main test phase ends. + + # Cleanup phase: shutdown CA + # Send SIGTERM signal to Control Agent + send_signal 15 ${ca_bin} + + # Now wait for process to log that it is exiting. + wait_for_message 10 "DCTL_SHUTDOWN" 1 + if [ ${_WAIT_FOR_MESSAGE} -eq 0 ]; then + printf "ERROR: Control Agent did not log shutdown.\n" + clean_exit 1 + fi + + # Make sure the server is down. + wait_for_server_down 5 ${ca_bin} + assert_eq 1 ${_WAIT_FOR_SERVER_DOWN} \ + "Expected wait_for_server_down return %d, returned %d" + + test_finish 0 +} + +shell_command_test "shell.no-auth" "" "list-commands" "fail" \ + "Failed to run: HTTP Error 401: Unauthorized" +shell_command_test "shell.bad-auth" \ + "--auth-user foo --auth-password bar" "list-commands" "fail" \ + "Failed to run: HTTP Error 401: Unauthorized" +shell_command_test "shell.authorized" \ + "--auth-user pet --auth-password meow" "list-commands" "" \ + "[ { \"arguments\": [ \"build-report\", \"config-get\", \"config-reload\", \"config-set\", \"config-test\", \"config-write\", \"list-commands\", \"shutdown\", \"status-get\", \"version-get\" ], \"result\": 0 } ]" -- GitLab From de85e6e564667453d21df038682f2e8f81dba0dd Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Mon, 13 Jul 2020 14:57:17 +0200 Subject: [PATCH 14/33] [#1304] Checkpoint: HA/CA tests to add --- doc/sphinx/arm/hooks-ha.rst | 24 +++++++++- src/hooks/dhcp/high_availability/ha_config.cc | 13 +++++- src/hooks/dhcp/high_availability/ha_config.h | 25 ++++++++-- .../high_availability/ha_config_parser.cc | 21 +++++++++ .../dhcp/high_availability/ha_service.cc | 7 +++ .../tests/ha_config_unittest.cc | 46 +++++++++++++++++++ 6 files changed, 129 insertions(+), 7 deletions(-) diff --git a/doc/sphinx/arm/hooks-ha.rst b/doc/sphinx/arm/hooks-ha.rst index 0da4ea04ed..a679cabaeb 100644 --- a/doc/sphinx/arm/hooks-ha.rst +++ b/doc/sphinx/arm/hooks-ha.rst @@ -470,6 +470,8 @@ with the only difference that ``this-server-name`` should be set to "name": "server3", "url": "http://192.168.56.99:8000/", "role": "backup", + "basic-auth-user": "foo", + "basic-auth-password": "bar", "auto-failover": false }] }] @@ -579,6 +581,9 @@ server. It may also contain an unlimited number of backup servers. In this example, there is one backup server which receives lease updates from the active servers. +Since Kea version 1.7.10 the basic HTTP authentication is available +to protect the Kea control agent against local attackers. + These are the parameters specified for each of the peers within this list: @@ -588,6 +593,15 @@ list: the control channel. Other servers use this URL to send control commands to that server. +- ``basic-auth-user`` - specifies the user id for basic HTTP + authentication. If not specified or specified to the empty string + no authentication header will be added to HTTP transactions. + Must not contain the colon (:) character. + +- ``basic-auth-password`` - specifies the password for basic HTTP + authentication. Ignored when the user id is not specified or empty. + The password is optional: if not specified an empty password is used. + - ``role`` - denotes the role of the server in the HA setup. The following roles are supported in the load-balancing configuration: ``primary``, ``secondary``, and ``backup``. There must be exactly one @@ -608,7 +622,9 @@ state, it can serve leases from both pools and it selects the pool which is appropriate for the received query. In other words, if the query would normally be processed by ``server2`` but this server is not available, ``server1`` will allocate the lease from the pool of -"192.0.3.200 - 192.0.3.250". +"192.0.3.200 - 192.0.3.250". The Kea control agent in front of the +``server3`` requires basic HTTP authentication and authorizes the +user id "foo" with the password "bar". .. _ha-load-balancing-advanced-config: @@ -754,6 +770,8 @@ hot-standby configuration: }, { "name": "server3", "url": "http://192.168.56.99:8000/", + "basic-auth-user": "foo", + "basic-auth-password": "bar", "role": "backup", "auto-failover": false }] @@ -830,6 +848,8 @@ passive-backup configuration: }, { "name": "server3", "url": "http://192.168.56.99:8000/", + "basic-auth-user": "foo", + "basic-auth-password": "bar", "role": "backup" }] }] @@ -1271,6 +1291,8 @@ load-balancing and the hot-standby cases presented in previous sections. } } +Since Kea version 1.7.10 the basic HTTP authentication is supported. + .. _ha-maintenance: Controlled Shutdown and Maintenance of DHCP servers diff --git a/src/hooks/dhcp/high_availability/ha_config.cc b/src/hooks/dhcp/high_availability/ha_config.cc index 6721040abe..d9aa89d0b2 100644 --- a/src/hooks/dhcp/high_availability/ha_config.cc +++ b/src/hooks/dhcp/high_availability/ha_config.cc @@ -10,13 +10,15 @@ #include #include +using namespace isc::http; using namespace isc::util; namespace isc { namespace ha { HAConfig::PeerConfig::PeerConfig() - : name_(), url_(""), role_(STANDBY), auto_failover_(false) { + : name_(), url_(""), role_(STANDBY), auto_failover_(false), + basic_auth_() { } void @@ -79,6 +81,15 @@ HAConfig::PeerConfig::roleToString(const HAConfig::PeerConfig::Role& role) { return (""); } +void +HAConfig::PeerConfig::addBasicAuthHttpHeader(PostHttpRequestJsonPtr request) const { + const BasicHttpAuthPtr& auth = getBasicAuth(); + if (!request || !auth) { + return; + } + request->context()->headers_.push_back(BasicAuthHttpHeaderContext(*auth)); +} + HAConfig::StateConfig::StateConfig(const int state) : state_(state), pausing_(STATE_PAUSE_NEVER) { } diff --git a/src/hooks/dhcp/high_availability/ha_config.h b/src/hooks/dhcp/high_availability/ha_config.h index 83b9891d2c..95c81b47c9 100644 --- a/src/hooks/dhcp/high_availability/ha_config.h +++ b/src/hooks/dhcp/high_availability/ha_config.h @@ -8,6 +8,8 @@ #define HA_CONFIG_H #include +#include +#include #include #include #include @@ -148,13 +150,26 @@ public: auto_failover_ = auto_failover; } - private: + /// @brief Returns non-const basic HTTP authentication. + http::BasicHttpAuthPtr& getBasicAuth() { + return (basic_auth_); + } + + /// @brief Returns const basic HTTP authentication. + const http::BasicHttpAuthPtr& getBasicAuth() const { + return (basic_auth_); + } + + /// @brief Adds a basic HTTP authentication header to a request. + void addBasicAuthHttpHeader(http::PostHttpRequestJsonPtr request) const; - std::string name_; ///< Server name. - http::Url url_; ///< Server URL. - Role role_; ///< Server role. - bool auto_failover_; ///< Auto failover state. + private: + std::string name_; ///< Server name. + http::Url url_; ///< Server URL. + Role role_; ///< Server role. + bool auto_failover_; ///< Auto failover state. + http::BasicHttpAuthPtr basic_auth_; ///< Basic HTTP authentication. }; /// @brief Pointer to the server's configuration. diff --git a/src/hooks/dhcp/high_availability/ha_config_parser.cc b/src/hooks/dhcp/high_availability/ha_config_parser.cc index 5e71910dce..7cba9c10cd 100644 --- a/src/hooks/dhcp/high_availability/ha_config_parser.cc +++ b/src/hooks/dhcp/high_availability/ha_config_parser.cc @@ -185,6 +185,27 @@ HAConfigParser::parseInternal(const HAConfigPtr& config_storage, // Auto failover configuration. cfg->setAutoFailover(getBoolean(*p, "auto-failover")); + + // Basic HTTP authentication password. + std::string password; + if ((*p)->contains("basic-auth-password")) { + password = getString((*p), "basic-auth-password"); + } + + // Basic HTTP authentication user. + if ((*p)->contains("basic-auth-user")) { + std::string user = getString((*p), "basic-auth-user"); + BasicHttpAuthPtr& auth = cfg->getBasicAuth(); + try { + if (!user.empty()) { + // Validate the user id value. + auth.reset(new BasicHttpAuth(user, password)); + } + } catch (const std::exception& ex) { + isc_throw(dhcp::DhcpConfigError, ex.what() << " in peer '" + << cfg->getName() << "'"); + } + } } // Per state configuration is optional. diff --git a/src/hooks/dhcp/high_availability/ha_service.cc b/src/hooks/dhcp/high_availability/ha_service.cc index 159a2cb377..345b2abf34 100644 --- a/src/hooks/dhcp/high_availability/ha_service.cc +++ b/src/hooks/dhcp/high_availability/ha_service.cc @@ -986,6 +986,7 @@ HAService::asyncSendLeaseUpdate(const QueryPtrType& query, PostHttpRequestJsonPtr request = boost::make_shared (HttpRequest::Method::HTTP_POST, "/", HttpVersion::HTTP_11(), HostHttpHeader(config->getUrl().getHostname())); + config->addBasicAuthHttpHeader(request); request->setBodyAsJson(command); request->finalize(); @@ -1268,6 +1269,7 @@ HAService::asyncSendHeartbeat() { PostHttpRequestJsonPtr request = boost::make_shared (HttpRequest::Method::HTTP_POST, "/", HttpVersion::HTTP_11(), HostHttpHeader(partner_config->getUrl().getHostname())); + partner_config->addBasicAuthHttpHeader(request); request->setBodyAsJson(CommandCreator::createHeartbeat(server_type_)); request->finalize(); @@ -1406,6 +1408,7 @@ HAService::asyncDisableDHCPService(HttpClient& http_client, (HttpRequest::Method::HTTP_POST, "/", HttpVersion::HTTP_11(), HostHttpHeader(remote_config->getUrl().getHostname())); + remote_config->addBasicAuthHttpHeader(request); request->setBodyAsJson(CommandCreator::createDHCPDisable(max_period, server_type_)); request->finalize(); @@ -1479,6 +1482,7 @@ HAService::asyncEnableDHCPService(HttpClient& http_client, PostHttpRequestJsonPtr request = boost::make_shared (HttpRequest::Method::HTTP_POST, "/", HttpVersion::HTTP_11(), HostHttpHeader(remote_config->getUrl().getHostname())); + remote_config->addBasicAuthHttpHeader(request); request->setBodyAsJson(CommandCreator::createDHCPEnable(server_type_)); request->finalize(); @@ -1612,6 +1616,7 @@ HAService::asyncSyncLeasesInternal(http::HttpClient& http_client, PostHttpRequestJsonPtr request = boost::make_shared (HttpRequest::Method::HTTP_POST, "/", HttpVersion::HTTP_11(), HostHttpHeader(partner_config->getUrl().getHostname())); + partner_config->addBasicAuthHttpHeader(request); if (server_type_ == HAServerType::DHCPv4) { request->setBodyAsJson(CommandCreator::createLease4GetPage( boost::dynamic_pointer_cast(last_lease), config_->getSyncPageLimit())); @@ -1949,6 +1954,7 @@ HAService::processMaintenanceStart() { PostHttpRequestJsonPtr request = boost::make_shared (HttpRequest::Method::HTTP_POST, "/", HttpVersion::HTTP_11(), HostHttpHeader(remote_config->getUrl().getHostname())); + remote_config->addBasicAuthHttpHeader(request); request->setBodyAsJson(CommandCreator::createMaintenanceNotify(false, server_type_)); request->finalize(); @@ -2070,6 +2076,7 @@ HAService::processMaintenanceCancel() { PostHttpRequestJsonPtr request = boost::make_shared (HttpRequest::Method::HTTP_POST, "/", HttpVersion::HTTP_11(), HostHttpHeader(remote_config->getUrl().getHostname())); + remote_config->addBasicAuthHttpHeader(request); request->setBodyAsJson(CommandCreator::createMaintenanceNotify(true, server_type_)); request->finalize(); diff --git a/src/hooks/dhcp/high_availability/tests/ha_config_unittest.cc b/src/hooks/dhcp/high_availability/tests/ha_config_unittest.cc index eae27780a7..3056dd39c5 100644 --- a/src/hooks/dhcp/high_availability/tests/ha_config_unittest.cc +++ b/src/hooks/dhcp/high_availability/tests/ha_config_unittest.cc @@ -79,16 +79,20 @@ TEST_F(HAConfigTest, configureLoadBalancing) { " \"name\": \"server1\"," " \"url\": \"http://127.0.0.1:8080/\"," " \"role\": \"primary\"," + " \"basic-auth-password\": \"1234\"," " \"auto-failover\": false" " }," " {" " \"name\": \"server2\"," " \"url\": \"http://127.0.0.1:8081/\"," + " \"basic-auth-user\": \"\"," " \"role\": \"secondary\"" " }," " {" " \"name\": \"server3\"," " \"url\": \"http://127.0.0.1:8082/\"," + " \"basic-auth-user\": \"foo\"," + " \"basic-auth-password\": \"bar\"," " \"role\": \"backup\"," " \"auto-failover\": false" " }" @@ -133,6 +137,7 @@ TEST_F(HAConfigTest, configureLoadBalancing) { EXPECT_EQ(cfg->getLogLabel(), "server1 (http://127.0.0.1:8080/)"); EXPECT_EQ(HAConfig::PeerConfig::PRIMARY, cfg->getRole()); EXPECT_FALSE(cfg->isAutoFailover()); + EXPECT_FALSE(cfg->getBasicAuth()); cfg = impl->getConfig()->getPeerConfig("server2"); ASSERT_TRUE(cfg); @@ -141,6 +146,7 @@ TEST_F(HAConfigTest, configureLoadBalancing) { EXPECT_EQ(cfg->getLogLabel(), "server2 (http://127.0.0.1:8081/)"); EXPECT_EQ(HAConfig::PeerConfig::SECONDARY, cfg->getRole()); EXPECT_TRUE(cfg->isAutoFailover()); + EXPECT_FALSE(cfg->getBasicAuth()); cfg = impl->getConfig()->getPeerConfig("server3"); ASSERT_TRUE(cfg); @@ -149,6 +155,8 @@ TEST_F(HAConfigTest, configureLoadBalancing) { EXPECT_EQ(cfg->getLogLabel(), "server3 (http://127.0.0.1:8082/)"); EXPECT_EQ(HAConfig::PeerConfig::BACKUP, cfg->getRole()); EXPECT_FALSE(cfg->isAutoFailover()); + ASSERT_TRUE(cfg->getBasicAuth()); + EXPECT_EQ("foo:bar", cfg->getBasicAuth()->getSecret()); // Verify that per-state configuration is correct.x @@ -200,6 +208,7 @@ TEST_F(HAConfigTest, configureHotStandby) { " {" " \"name\": \"server1\"," " \"url\": \"http://127.0.0.1:8080/\"," + " \"basic-auth-user\": \"admin\"," " \"role\": \"primary\"," " \"auto-failover\": false" " }," @@ -238,6 +247,8 @@ TEST_F(HAConfigTest, configureHotStandby) { EXPECT_EQ("http://127.0.0.1:8080/", cfg->getUrl().toText()); EXPECT_EQ(HAConfig::PeerConfig::PRIMARY, cfg->getRole()); EXPECT_FALSE(cfg->isAutoFailover()); + ASSERT_TRUE(cfg->getBasicAuth()); + EXPECT_EQ("admin:", cfg->getBasicAuth()->getSecret()); cfg = impl->getConfig()->getPeerConfig("server2"); ASSERT_TRUE(cfg); @@ -245,6 +256,7 @@ TEST_F(HAConfigTest, configureHotStandby) { EXPECT_EQ("http://127.0.0.1:8081/", cfg->getUrl().toText()); EXPECT_EQ(HAConfig::PeerConfig::STANDBY, cfg->getRole()); EXPECT_TRUE(cfg->isAutoFailover()); + EXPECT_FALSE(cfg->getBasicAuth()); cfg = impl->getConfig()->getPeerConfig("server3"); ASSERT_TRUE(cfg); @@ -252,6 +264,7 @@ TEST_F(HAConfigTest, configureHotStandby) { EXPECT_EQ("http://127.0.0.1:8082/", cfg->getUrl().toText()); EXPECT_EQ(HAConfig::PeerConfig::BACKUP, cfg->getRole()); EXPECT_FALSE(cfg->isAutoFailover()); + EXPECT_FALSE(cfg->getBasicAuth()); HAConfig::StateConfigPtr state_cfg; ASSERT_NO_THROW(state_cfg = impl->getConfig()->getStateMachineConfig()-> @@ -312,6 +325,8 @@ TEST_F(HAConfigTest, configurePassiveBackup) { " {" " \"name\": \"server3\"," " \"url\": \"http://127.0.0.1:8082/\"," + " \"basic-auth-user\": \"test\"," + " \"basic-auth-password\": \"123\\u00a3\"," " \"role\": \"backup\"" " }" " ]" @@ -330,18 +345,22 @@ TEST_F(HAConfigTest, configurePassiveBackup) { EXPECT_EQ("server1", cfg->getName()); EXPECT_EQ("http://127.0.0.1:8080/", cfg->getUrl().toText()); EXPECT_EQ(HAConfig::PeerConfig::PRIMARY, cfg->getRole()); + EXPECT_FALSE(cfg->getBasicAuth()); cfg = impl->getConfig()->getPeerConfig("server2"); ASSERT_TRUE(cfg); EXPECT_EQ("server2", cfg->getName()); EXPECT_EQ("http://127.0.0.1:8081/", cfg->getUrl().toText()); EXPECT_EQ(HAConfig::PeerConfig::BACKUP, cfg->getRole()); + EXPECT_FALSE(cfg->getBasicAuth()); cfg = impl->getConfig()->getPeerConfig("server3"); ASSERT_TRUE(cfg); EXPECT_EQ("server3", cfg->getName()); EXPECT_EQ("http://127.0.0.1:8082/", cfg->getUrl().toText()); EXPECT_EQ(HAConfig::PeerConfig::BACKUP, cfg->getRole()); + ASSERT_TRUE(cfg->getBasicAuth()); + EXPECT_EQ("dGVzdDoxMjPCow==", cfg->getBasicAuth()->getCredential()); } // This server name must not be empty. @@ -1135,6 +1154,33 @@ TEST_F(HAConfigTest, passiveBackupNoPrimary) { "primary server required in the passive backup configuration"); } +// Test that empty name id is forbidden for basic HTTP authentication. +TEST_F(HAConfigTest, invalidUser) { + testInvalidConfig( + "[" + " {" + " \"this-server-name\": \"server1\"," + " \"mode\": \"load-balancing\"," + " \"peers\": [" + " {" + " \"name\": \"server1\"," + " \"url\": \"http://127.0.0.1:8080/\"," + " \"role\": \"primary\"," + " \"auto-failover\": false" + " }," + " {" + " \"name\": \"server2\"," + " \"url\": \":http//127.0.0.1:8080/\"," + " \"basic-auth-user\": \"foo:bar\"," + " \"role\": \"secondary\"," + " \"auto-failover\": true" + " }" + " ]" + " }" + "]", + "user 'foo:bar' must not contain a ':' in peer 'server2'"); +} + // Test that conversion of the role names works correctly. TEST_F(HAConfigTest, stringToRole) { -- GitLab From e3aa8a60640fca0ece0c44fee3f4175736955994 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Tue, 14 Jul 2020 13:04:12 +0200 Subject: [PATCH 15/33] [#1304] Finished HA service tests --- .../dhcp/high_availability/ha_service.cc | 19 +- .../tests/ha_service_unittest.cc | 1266 +++++++++++++++-- 2 files changed, 1197 insertions(+), 88 deletions(-) diff --git a/src/hooks/dhcp/high_availability/ha_service.cc b/src/hooks/dhcp/high_availability/ha_service.cc index 345b2abf34..bda327dea1 100644 --- a/src/hooks/dhcp/high_availability/ha_service.cc +++ b/src/hooks/dhcp/high_availability/ha_service.cc @@ -2156,6 +2156,8 @@ HAService::processMaintenanceCancel() { ConstElementPtr HAService::verifyAsyncResponse(const HttpResponsePtr& response, int& rcode) { + // Set the return code to error in case of early throw. + rcode = CONTROL_RESULT_ERROR; // The response must cast to JSON type. HttpResponseJsonPtr json_response = boost::dynamic_pointer_cast(response); @@ -2169,9 +2171,22 @@ HAService::verifyAsyncResponse(const HttpResponsePtr& response, int& rcode) { isc_throw(CtrlChannelError, "no body found in the response"); } - // Body must contain a list of responses form multiple servers. + // Body should contain a list of responses from multiple servers. if (body->getType() != Element::list) { - isc_throw(CtrlChannelError, "body of the response must be a list"); + // Some control agent errors are returned as a map. + if (body->getType() == Element::map) { + ElementPtr list = Element::createList(); + ElementPtr answer = Element::createMap(); + answer->set(CONTROL_RESULT, Element::create(rcode)); + ConstElementPtr text = body->get(CONTROL_TEXT); + if (text) { + answer->set(CONTROL_TEXT, text); + } + list->add(answer); + body = list; + } else { + isc_throw(CtrlChannelError, "body of the response must be a list"); + } } // There must be at least one response. diff --git a/src/hooks/dhcp/high_availability/tests/ha_service_unittest.cc b/src/hooks/dhcp/high_availability/tests/ha_service_unittest.cc index f8f74b215a..73ad5b9e1c 100644 --- a/src/hooks/dhcp/high_availability/tests/ha_service_unittest.cc +++ b/src/hooks/dhcp/high_availability/tests/ha_service_unittest.cc @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -214,7 +215,7 @@ public: TestHttpResponseCreator() : requests_(), control_result_(CONTROL_RESULT_SUCCESS), arguments_(), per_request_control_result_(), - per_request_arguments_(), request_index_() { + per_request_arguments_(), request_index_(), basic_auth_() { } /// @brief Removes all received requests. @@ -308,6 +309,21 @@ public: return (HttpRequestPtr(new PostHttpRequestJson())); } + /// @brief Get basic HTTP authentication credentials. + /// + /// @return Basic HTTP authentication credentials and user id map. + const BasicHttpAuthMap& getCredentials() const { + return (basic_auth_.getCredentialMap()); + } + + /// @brief Add basic HTTP authentication client. + /// + /// @param user The user id to authorize. + /// @param password The password. + void addBasicAuth(const std::string& user, const std::string& password) { + basic_auth_.add(user, password); + } + private: /// @brief Creates HTTP response. @@ -340,6 +356,31 @@ private: /// @return Pointer to the generated HTTP OK response. virtual HttpResponsePtr createDynamicHttpResponse(const ConstHttpRequestPtr& request) { + // Check authentication. + const BasicHttpAuthMap& credentials = getCredentials(); + if (!credentials.empty()) { + bool authorized = false; + try { + std::string value = request->getHeaderValue("Authorization"); + if (value.size() < 8) { + isc_throw(isc::BadValue, "header content is too short"); + } + if (value.substr(0, 6) != "Basic ") { + isc_throw(isc::BadValue, "no basic authentication"); + } + value = value.substr(6); + if (credentials.count(value) != 0) { + authorized = true; + } + } catch (const std::exception&) { + authorized = false; + } + if (!authorized) { + return (createStockHttpResponse(request, + HttpStatusCode::UNAUTHORIZED)); + } + } + // Request must always be JSON. ConstPostHttpRequestJsonPtr request_json = boost::dynamic_pointer_cast(request); @@ -447,6 +488,9 @@ private: /// @brief Index of the next request of the given type. std::map request_index_; + + /// @brief Basic HTTP authentication configuration. + BasicHttpAuthConfig basic_auth_; }; /// @brief Shared pointer to the @c TestHttpResponseCreator. @@ -532,7 +576,13 @@ public: HttpListener::RequestTimeout(REQUEST_TIMEOUT), HttpListener::IdleTimeout(IDLE_TIMEOUT))), leases4_(), - leases6_() { + leases6_(), + user1_(""), + password1_(""), + user2_(""), + password2_(""), + user3_(""), + password3_("") { MultiThreadingMgr::instance().setMode(false); } @@ -658,6 +708,43 @@ public: factory3_->getResponseCreator()->setArguments("lease6-get-page", response_arguments); } + /// @brief Set basic HTTP authentication in a config. + /// + /// @param config Configuration to update. + void setBasicAuth(HAConfigPtr config) { + if (!config) { + ADD_FAILURE() << "null config"; + return; + } + if (!user1_.empty()) { + HAConfig::PeerConfigPtr peer = config->getPeerConfig("server1"); + if (!peer) { + ADD_FAILURE() << "null server1 config"; + return; + } + BasicHttpAuthPtr& auth = peer->getBasicAuth(); + auth.reset(new BasicHttpAuth(user1_, password1_)); + } + if (!user2_.empty()) { + HAConfig::PeerConfigPtr peer = config->getPeerConfig("server2"); + if (!peer) { + ADD_FAILURE() << "null server2 config"; + return; + } + BasicHttpAuthPtr& auth = peer->getBasicAuth(); + auth.reset(new BasicHttpAuth(user2_, password2_)); + } + if (!user3_.empty()) { + HAConfig::PeerConfigPtr peer = config->getPeerConfig("server3"); + if (!peer) { + ADD_FAILURE() << "null server3 config"; + return; + } + BasicHttpAuthPtr& auth = peer->getBasicAuth(); + auth.reset(new BasicHttpAuth(user3_, password3_)); + } + } + /// @brief Tests scenarios when lease updates are sent to a partner while /// the partner is online or offline. /// @@ -677,6 +764,7 @@ public: // server 1. HAConfigPtr config_storage = createValidConfiguration(); config_storage->setWaitBackupAck(wait_backup_ack); + setBasicAuth(config_storage); // Create parking lot where query is going to be parked and unparked. ParkingLotPtr parking_lot(new ParkingLot()); @@ -779,6 +867,7 @@ public: // server 1. HAConfigPtr config_storage = createValidConfiguration(); config_storage->setWaitBackupAck(wait_backup_ack); + setBasicAuth(config_storage); // Create parking lot where query is going to be parked and unparked. ParkingLotPtr parking_lot(new ParkingLot()); @@ -871,6 +960,7 @@ public: // server 1. HAConfigPtr config_storage = createValidConfiguration(); config_storage->setHeartbeatDelay(1000); + setBasicAuth(config_storage); // Create a valid static response to the heartbeat command. ElementPtr response_arguments = Element::createMap(); @@ -1035,7 +1125,7 @@ public: // Instruct the server 2 to return an error as a result of receiving a command. factory2_->getResponseCreator()->setControlResult(CONTROL_RESULT_ERROR); - // Start only two servers out of three. The server 3 is not running. + // Start HTTP servers. ASSERT_NO_THROW({ listener_->start(); listener2_->start(); @@ -1079,6 +1169,44 @@ public: EXPECT_TRUE(delete_request3); } + /// @brief Tests scenarios when one of the servers to which a + /// lease update is sent does not authorize the local server. + void testSndUpdatesControlResultUnauthorized() { + // Instruct the server 2 to require authentication. + factory2_->getResponseCreator()->addBasicAuth("foo", "bar"); + + // Start HTTP servers. + ASSERT_NO_THROW({ + listener_->start(); + listener2_->start(); + listener3_->start(); + }); + + testSendLeaseUpdates([] { + ADD_FAILURE() << "unpark function called but expected that " + "the packet is dropped"; + }, false, 1); + + // The updates should be sent to server 2 and this server should + // return error code. + EXPECT_TRUE(factory2_->getResponseCreator()->getReceivedRequests().empty()); + + // Lease updates should be successfully sent to server3. + EXPECT_EQ(2, factory3_->getResponseCreator()->getReceivedRequests().size()); + + // Check that the server 3 has received lease4-update command. + auto update_request3 = + factory3_->getResponseCreator()->findRequest("lease4-update", + "192.1.2.3"); + EXPECT_TRUE(update_request3); + + // Check that the server 3 has received lease4-del command. + auto delete_request3 = + factory3_->getResponseCreator()->findRequest("lease4-del", + "192.2.3.4"); + EXPECT_TRUE(delete_request3); + } + /// @brief Tests scenarios when one of the servers to which /// updates are sent is offline. void testSendUpdatesBackupServerOffline() { @@ -1249,7 +1377,7 @@ public: // Instruct the server 2 to return an error as a result of receiving a command. factory2_->getResponseCreator()->setControlResult(CONTROL_RESULT_ERROR); - // Start only two servers out of three. The server 3 is not running. + // Start HTTP servers. ASSERT_NO_THROW({ listener_->start(); listener2_->start(); @@ -1272,6 +1400,28 @@ public: EXPECT_TRUE(update_request2); } + /// @brief Tests scenarios when one of the servers to which a + /// lease update is sent does not authorize the local server. + void testSendUpdatesControlResultUnauthorized6() { + // Instruct the server 2 to require authentication. + factory2_->getResponseCreator()->addBasicAuth("foo", "bar"); + + // Start HTTP servers. + ASSERT_NO_THROW({ + listener_->start(); + listener2_->start(); + listener3_->start(); + }); + + testSendLeaseUpdates6([] { + ADD_FAILURE() << "unpark function called but expected that " + "the packet is dropped"; + }, false, 1); + + // The updates should be sent to server 2 and this server should return error code. + EXPECT_TRUE(factory2_->getResponseCreator()->getReceivedRequests().empty()); + } + /// @brief These tests verify that the server accepts the response /// to the lease6-bulk-apply command including /// failed-deleted-leases and failed-leases parameters. @@ -1365,6 +1515,7 @@ public: // Create HA configuration for 3 servers. This server is // server 1. HAConfigPtr config_storage = createValidConfiguration(); + setBasicAuth(config_storage); // Leases are fetched in pages, so the lease4-get-page should be // sent multiple times. The server is configured to return leases @@ -1413,6 +1564,7 @@ public: // Create HA configuration for 3 servers. This server is // server 1. HAConfigPtr config_storage = createValidConfiguration(); + setBasicAuth(config_storage); // Leases are fetched in pages, so the lease6-get-page should be // sent multiple times. The server is configured to return leases @@ -1466,6 +1618,24 @@ public: /// @brief IPv6 leases to be used in the tests. std::vector leases6_; + + /// @brief Basic HTTP authentication user id for server1. + std::string user1_; + + /// @brief Basic HTTP authentication password for server1. + std::string password1_; + + /// @brief Basic HTTP authentication user id for server2. + std::string user2_; + + /// @brief Basic HTTP authentication password for server2. + std::string password2_; + + /// @brief Basic HTTP authentication user id for server3. + std::string user3_; + + /// @brief Basic HTTP authentication password for server3. + std::string password3_; }; // Test that server performs load balancing and assigns appropriate classes @@ -1627,6 +1797,33 @@ TEST_F(HAServiceTest, sendSuccessfulUpdatesMultiThreading) { testSendSuccessfulUpdates(); } +// Test scenario when all lease updates are sent successfully. +TEST_F(HAServiceTest, sendSuccessfulUpdatesAuthorized) { + // Update config to provide authentication. + user2_ = "foo"; + password2_ = "bar"; + user3_ = "test"; + password3_ = "1234"; + // Instruct servers to require authentication. + factory2_->getResponseCreator()->addBasicAuth("foo", "bar"); + factory3_->getResponseCreator()->addBasicAuth("test", "1234"); + testSendSuccessfulUpdates(); +} + +// Test scenario when all lease updates are sent successfully. +TEST_F(HAServiceTest, sendSuccessfulUpdatesAuthorizedMultiThreading) { + // Update config to provide authentication. + user2_ = "foo"; + password2_ = "bar"; + user3_ = "test"; + password3_ = "1234"; + // Instruct servers to require authentication. + factory2_->getResponseCreator()->addBasicAuth("foo", "bar"); + factory3_->getResponseCreator()->addBasicAuth("test", "1234"); + MultiThreadingMgr::instance().setMode(true); + testSendSuccessfulUpdates(); +} + // Test scenario when lease updates are not sent to the failover peer. TEST_F(HAServiceTest, sendUpdatesPartnerDown) { testSendUpdatesPartnerDown(); @@ -1673,6 +1870,19 @@ TEST_F(HAServiceTest, sendUpdatesControlResultErrorMultiThreading) { testSndUpdatesControlResultError(); } +// Test scenario when one of the servers to which a lease update is sent +// requires not provided authentication. +TEST_F(HAServiceTest, sendUpdatesControlResultUnauthorized) { + testSndUpdatesControlResultUnauthorized(); +} + +// Test scenario when one of the servers to which a lease update is sent +// requires not provided authentication. +TEST_F(HAServiceTest, sendUpdatesControlResultUnauthorizedMultiThreading) { + MultiThreadingMgr::instance().setMode(true); + testSndUpdatesControlResultUnauthorized(); +} + // Test scenario when all lease updates are sent successfully. TEST_F(HAServiceTest, sendSuccessfulUpdates6) { testSendSuccessfulUpdates6(); @@ -1683,6 +1893,34 @@ TEST_F(HAServiceTest, sendSuccessfulUpdates6MultiThreading) { MultiThreadingMgr::instance().setMode(true); testSendSuccessfulUpdates6(); } + +// Test scenario when all lease updates are sent successfully. +TEST_F(HAServiceTest, sendSuccessfulUpdates6Authorized) { + // Update config to provide authentication. + user2_ = "foo"; + password2_ = "bar"; + user3_ = "test"; + password3_ = "1234"; + // Instruct servers to require authentication. + factory2_->getResponseCreator()->addBasicAuth("foo", "bar"); + factory3_->getResponseCreator()->addBasicAuth("test", "1234"); + testSendSuccessfulUpdates6(); +} + +// Test scenario when all lease updates are sent successfully. +TEST_F(HAServiceTest, sendSuccessfulUpdates6AuthorizedMultiThreading) { + // Update config to provide authentication. + user2_ = "foo"; + password2_ = "bar"; + user3_ = "test"; + password3_ = "1234"; + // Instruct servers to require authentication. + factory2_->getResponseCreator()->addBasicAuth("foo", "bar"); + factory3_->getResponseCreator()->addBasicAuth("test", "1234"); + MultiThreadingMgr::instance().setMode(true); + testSendSuccessfulUpdates6(); +} + // Test scenario when lease updates are not sent to the failover peer. TEST_F(HAServiceTest, sendUpdatesPartnerDown6) { testSendUpdatesPartnerDown6(); @@ -1729,6 +1967,19 @@ TEST_F(HAServiceTest, sendUpdatesControlResultError6MultiThreading) { testSendUpdatesControlResultError6(); } +// Test scenario when one of the servers to which a lease update is sent +// requires not provided authentication. +TEST_F(HAServiceTest, sendUpdatesControlResultUnauthorized6) { + testSendUpdatesControlResultUnauthorized6(); +} + +// Test scenario when one of the servers to which a lease update is sent +// requires not provided authentication. +TEST_F(HAServiceTest, sendUpdatesControlResultUnauthorized6MultiThreading) { + MultiThreadingMgr::instance().setMode(true); + testSendUpdatesControlResultUnauthorized6(); +} + // This test verifies that the server accepts the response to the lease6-bulk-apply // command including failed-deleted-leases and failed-leases parameters. TEST_F(HAServiceTest, sendUpdatesFailedLeases6) { @@ -1870,6 +2121,32 @@ TEST_F(HAServiceTest, recurringHeartbeat) { EXPECT_GE(factory2_->getResponseCreator()->getReceivedRequests().size(), 0); } +// This test verifies that the heartbeat is periodically sent to the +// other server. +TEST_F(HAServiceTest, recurringHeartbeatAuthorized) { + // Update config to provide authentication. + user2_ = "foo"; + password2_ = "bar"; + user3_ = "test"; + password3_ = "1234"; + // Instruct servers to require authentication. + factory2_->getResponseCreator()->addBasicAuth("foo", "bar"); + factory3_->getResponseCreator()->addBasicAuth("test", "1234"); + // Start the servers. + ASSERT_NO_THROW({ + listener_->start(); + listener2_->start(); + listener3_->start(); + }); + + // All servers are configured to return success and all servers are online. + // The heartbeat should be successful (as indicated by the 'true' argument). + ASSERT_NO_FATAL_FAILURE(testRecurringHeartbeat(CONTROL_RESULT_SUCCESS, true)); + + // Server 2 should have received the heartbeat + EXPECT_GE(factory2_->getResponseCreator()->getReceivedRequests().size(), 0); +} + // This test verifies that the heartbeat is considered being unsuccessful if the // partner is offline. TEST_F(HAServiceTest, recurringHeartbeatServerOffline) { @@ -1905,6 +2182,28 @@ TEST_F(HAServiceTest, recurringHeartbeatControlResultError) { EXPECT_EQ(1, factory2_->getResponseCreator()->getReceivedRequests().size()); } +// This test verifies that the heartbeat is considered being unsuccessful if +// the partner requires not provided authentication. +TEST_F(HAServiceTest, recurringHeartbeatControlResultUnauthorized) { + // Instruct servers to require authentication. + factory2_->getResponseCreator()->addBasicAuth("foo", "bar"); + factory3_->getResponseCreator()->addBasicAuth("test", "1234"); + + // Start the servers. + ASSERT_NO_THROW({ + listener_->start(); + listener2_->start(); + listener3_->start(); + }); + + // Run the actual test. The servers return a control error and it is expected + // that the state is not poked. + ASSERT_NO_FATAL_FAILURE(testRecurringHeartbeat(CONTROL_RESULT_ERROR, false)); + + // Server 2 should have received the heartbeat. + EXPECT_TRUE(factory2_->getResponseCreator()->getReceivedRequests().empty()); +} + // This test verifies that IPv4 leases can be fetched from the peer and inserted // or updated in the local lease database. TEST_F(HAServiceTest, asyncSyncLeases) { @@ -1946,6 +2245,7 @@ TEST_F(HAServiceTest, asyncSyncLeases) { // Create HA configuration. HAConfigPtr config_storage = createValidConfiguration(); + setBasicAuth(config_storage); // Convert leases to the JSON format, the same as used by the lease_cmds // hook library. Configure our test HTTP servers to return those @@ -2023,79 +2323,33 @@ TEST_F(HAServiceTest, asyncSyncLeases) { } } -// Test that there is no exception thrown during leases synchronization -// when server returns a wrong answer. -TEST_F(HAServiceTest, asyncSyncLeasesWrongAnswer) { +// This test verifies that IPv4 leases can be fetched from the peer and inserted +// or updated in the local lease database. +TEST_F(HAServiceTest, asyncSyncLeasesAuthorized) { + // Update config to provide authentication. + user2_ = "foo"; + password2_ = "bar"; + user3_ = "test"; + password3_ = "1234"; + + // Instruct servers to require authentication. + factory2_->getResponseCreator()->addBasicAuth("foo", "bar"); + factory3_->getResponseCreator()->addBasicAuth("test", "1234"); + // Create lease manager. ASSERT_NO_THROW(LeaseMgrFactory::create("universe=4 type=memfile persist=false")); // Create IPv4 leases which will be fetched from the other server. ASSERT_NO_THROW(generateTestLeases4()); - // Create HA configuration. - HAConfigPtr config_storage = createValidConfiguration(); - // Setting the heartbeat delay to 0 disables the recurring heartbeat. - // We just want to synchronize leases and not send the heartbeat. - config_storage->setHeartbeatDelay(0); - - // Set empty response. This should cause the HA service to log an - // error but not crash. - ElementPtr response_arguments = Element::createMap(); - - factory2_->getResponseCreator()->setArguments(response_arguments); - factory3_->getResponseCreator()->setArguments(response_arguments); - - // Start the servers. - ASSERT_NO_THROW({ - listener_->start(); - listener2_->start(); - listener3_->start(); - }); - - TestHAService service(io_service_, network_state_, config_storage); - - // Start fetching leases asynchronously. - ASSERT_NO_THROW(service.asyncSyncLeases()); - - // Run IO service to actually perform the transaction. - ASSERT_NO_THROW(runIOService(1000)); -} - -// Test that there is no exception thrown during leases synchronization -// when servers are offline. -TEST_F(HAServiceTest, asyncSyncLeasesServerOffline) { - // Create HA configuration. - HAConfigPtr config_storage = createValidConfiguration(); - // Setting the heartbeat delay to 0 disables the recurring heartbeat. - // We just want to synchronize leases and not send the heartbeat. - config_storage->setHeartbeatDelay(0); - - TestHAService service(io_service_, network_state_, config_storage); - - // Start fetching leases asynchronously. - ASSERT_NO_THROW(service.asyncSyncLeases()); - - // Run IO service for 1 second. - ASSERT_NO_THROW(runIOService(1000)); -} - -// This test verifies that IPv6 leases can be fetched from the peer and inserted -// or updated in the local lease database. -TEST_F(HAServiceTest, asyncSyncLeases6) { - // Create lease manager. - ASSERT_NO_THROW(LeaseMgrFactory::create("universe=6 type=memfile persist=false")); - - // Create IPv6 leases which will be fetched from the other server. - ASSERT_NO_THROW(generateTestLeases6()); - - for (size_t i = 0; i < leases6_.size(); ++i) { + for (size_t i = 0; i < leases4_.size(); ++i) { // For every even lease index we add this lease to the database to exercise // the scenario when a lease is already in the database and may be updated // by the lease synchronization procedure. if ((i % 2) == 0) { // Add a copy of the lease to make sure that by modifying the lease // contents we don't affect the lease in the database. - Lease6Ptr lease_to_add(new Lease6(*leases6_[i])); + Lease4Ptr lease_to_add(new Lease4(*leases4_[i])); // Modify valid lifetime of the lease in the database so we can // later use this value to verify if the lease has been updated. --lease_to_add->valid_lft_; @@ -2107,19 +2361,20 @@ TEST_F(HAServiceTest, asyncSyncLeases6) { // of synchrnonization process because cltt is checked and the lease is // updated if the cltt of the fetched lease is later than the cltt of the // existing lease. - ++leases6_[0]->cltt_; + ++leases4_[0]->cltt_; // For the second lease, set the wrong subnet identifier. This should be // rejected and this lease shouldn't be inserted into the database. // Other leases should be inserted/updated just fine. - ++leases6_[1]->subnet_id_ = 0; + ++leases4_[1]->subnet_id_ = 0; // Modify the partner's lease cltt so it is earlier than the local lease. // Therfore, this lease update should be rejected. - --leases6_[2]->cltt_; + --leases4_[2]->cltt_; // Create HA configuration. HAConfigPtr config_storage = createValidConfiguration(); + setBasicAuth(config_storage); // Convert leases to the JSON format, the same as used by the lease_cmds // hook library. Configure our test HTTP servers to return those @@ -2127,9 +2382,9 @@ TEST_F(HAServiceTest, asyncSyncLeases6) { ElementPtr response_arguments = Element::createMap(); // Leases are fetched in pages, so the lease4-get-page should be - // sent multiple times. We need to configure the server side to - // return leases in 3-element chunks. - createPagedSyncResponses6(); + // sent multiple times. The server is configured to return leases + // in 3-element chunks. + createPagedSyncResponses4(); // Start the servers. ASSERT_NO_THROW({ @@ -2138,8 +2393,7 @@ TEST_F(HAServiceTest, asyncSyncLeases6) { listener3_->start(); }); - TestHAService service(io_service_, network_state_, config_storage, - HAServerType::DHCPv6); + TestHAService service(io_service_, network_state_, config_storage); // Setting the heartbeat delay to 0 disables the recurring heartbeat. // We just want to synchronize leases and not send the heartbeat. config_storage->setHeartbeatDelay(0); @@ -2152,30 +2406,373 @@ TEST_F(HAServiceTest, asyncSyncLeases6) { // Stop running the IO service if we see a lease in the lease // database which is expected to be inserted as a result of lease // syncing. - return (!LeaseMgrFactory::instance().getLeases6(SubnetID(10)).empty()); + return (!LeaseMgrFactory::instance().getLeases4(SubnetID(10)).empty()); })); // Check if all leases have been stored in the local database. - for (size_t i = 0; i < leases6_.size(); ++i) { + for (size_t i = 0; i < leases4_.size(); ++i) { if (i == 1) { // This lease was purposely malformed and thus shouldn't be // inserted into the database. - EXPECT_FALSE(LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, - leases6_[i]->addr_)) - << "lease " << leases6_[i]->addr_.toText() + EXPECT_FALSE(LeaseMgrFactory::instance().getLease4(leases4_[i]->addr_)) + << "lease " << leases4_[i]->addr_.toText() << " was inserted into the database, but it shouldn't"; + } else { - // Other leases should be inserted/updated. - Lease6Ptr existing_lease = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, - leases6_[i]->addr_); - ASSERT_TRUE(existing_lease) << "lease " << leases6_[i]->addr_.toText() + // All other leases should be in the database. + Lease4Ptr existing_lease = LeaseMgrFactory::instance().getLease4(leases4_[i]->addr_); + ASSERT_TRUE(existing_lease) << "lease " << leases4_[i]->addr_.toText() << " not in the lease database"; - + // The lease with #2 returned by the partner is older than its local instance. + // The local server should reject this lease. if (i == 2) { // The existing lease should have unmodified timestamp because the // update is expected to be rejected. Same for valid lifetime. - EXPECT_LT(leases6_[i]->cltt_, existing_lease->cltt_); - EXPECT_NE(leases6_[i]->valid_lft_, existing_lease->valid_lft_); + EXPECT_LT(leases4_[i]->cltt_, existing_lease->cltt_); + EXPECT_NE(leases4_[i]->valid_lft_, existing_lease->valid_lft_); + + } else { + // All other leases should have the same cltt. + EXPECT_EQ(leases4_[i]->cltt_, existing_lease->cltt_); + + // Leases with even indexes were added to the database with modified + // valid lifetime. Thus the local copy of each such lease should have + // this modified valid lifetime. The lease #0 should be updated from + // the partner because of the partner's cltt was set to later time. + if ((i != 0) && (i % 2) == 0) { + EXPECT_EQ(leases4_[i]->valid_lft_ - 1, existing_lease->valid_lft_); + + } else { + // All other leases should have been fetched from the partner and + // inserted with no change. + EXPECT_EQ(leases4_[i]->valid_lft_, existing_lease->valid_lft_); + } + } + } + } +} + +// Test that there is no exception thrown during leases synchronization +// when server returns a wrong answer. +TEST_F(HAServiceTest, asyncSyncLeasesWrongAnswer) { + // Create lease manager. + ASSERT_NO_THROW(LeaseMgrFactory::create("universe=4 type=memfile persist=false")); + + // Create IPv4 leases which will be fetched from the other server. + ASSERT_NO_THROW(generateTestLeases4()); + + // Create HA configuration. + HAConfigPtr config_storage = createValidConfiguration(); + // Setting the heartbeat delay to 0 disables the recurring heartbeat. + // We just want to synchronize leases and not send the heartbeat. + config_storage->setHeartbeatDelay(0); + + // Set empty response. This should cause the HA service to log an + // error but not crash. + ElementPtr response_arguments = Element::createMap(); + + factory2_->getResponseCreator()->setArguments(response_arguments); + factory3_->getResponseCreator()->setArguments(response_arguments); + + // Start the servers. + ASSERT_NO_THROW({ + listener_->start(); + listener2_->start(); + listener3_->start(); + }); + + TestHAService service(io_service_, network_state_, config_storage); + + // Start fetching leases asynchronously. + ASSERT_NO_THROW(service.asyncSyncLeases()); + + // Run IO service to actually perform the transaction. + ASSERT_NO_THROW(runIOService(1000)); +} + +// Test that there is no exception thrown during leases synchronization +// when servers are offline. +TEST_F(HAServiceTest, asyncSyncLeasesServerOffline) { + // Create HA configuration. + HAConfigPtr config_storage = createValidConfiguration(); + // Setting the heartbeat delay to 0 disables the recurring heartbeat. + // We just want to synchronize leases and not send the heartbeat. + config_storage->setHeartbeatDelay(0); + + TestHAService service(io_service_, network_state_, config_storage); + + // Start fetching leases asynchronously. + ASSERT_NO_THROW(service.asyncSyncLeases()); + + // Run IO service for 1 second. + ASSERT_NO_THROW(runIOService(1000)); +} + +// Test that there is no exception thrown during leases synchronization +// when servers require not provided authentication. +TEST_F(HAServiceTest, asyncSyncLeasesServerUnauthorized) { + // Instruct servers to require authentication. + factory2_->getResponseCreator()->addBasicAuth("foo", "bar"); + factory3_->getResponseCreator()->addBasicAuth("test", "1234"); + + // Create lease manager. + ASSERT_NO_THROW(LeaseMgrFactory::create("universe=4 type=memfile persist=false")); + + // Create IPv4 leases which will be fetched from the other server. + ASSERT_NO_THROW(generateTestLeases4()); + + // Create HA configuration. + HAConfigPtr config_storage = createValidConfiguration(); + setBasicAuth(config_storage); + + // Setting the heartbeat delay to 0 disables the recurring heartbeat. + // We just want to synchronize leases and not send the heartbeat. + config_storage->setHeartbeatDelay(0); + + // Start the servers. + ASSERT_NO_THROW({ + listener_->start(); + listener2_->start(); + listener3_->start(); + }); + + TestHAService service(io_service_, network_state_, config_storage); + + // Start fetching leases asynchronously. + ASSERT_NO_THROW(service.asyncSyncLeases()); + + // Run IO service for 1 second. + ASSERT_NO_THROW(runIOService(1000)); +} + +// This test verifies that IPv6 leases can be fetched from the peer and inserted +// or updated in the local lease database. +TEST_F(HAServiceTest, asyncSyncLeases6) { + // Create lease manager. + ASSERT_NO_THROW(LeaseMgrFactory::create("universe=6 type=memfile persist=false")); + + // Create IPv6 leases which will be fetched from the other server. + ASSERT_NO_THROW(generateTestLeases6()); + + for (size_t i = 0; i < leases6_.size(); ++i) { + // For every even lease index we add this lease to the database to exercise + // the scenario when a lease is already in the database and may be updated + // by the lease synchronization procedure. + if ((i % 2) == 0) { + // Add a copy of the lease to make sure that by modifying the lease + // contents we don't affect the lease in the database. + Lease6Ptr lease_to_add(new Lease6(*leases6_[i])); + // Modify valid lifetime of the lease in the database so we can + // later use this value to verify if the lease has been updated. + --lease_to_add->valid_lft_; + LeaseMgrFactory::instance().addLease(lease_to_add); + } + } + + // Modify cltt of the first lease. This lease should be updated as a result + // of synchrnonization process because cltt is checked and the lease is + // updated if the cltt of the fetched lease is later than the cltt of the + // existing lease. + ++leases6_[0]->cltt_; + + // For the second lease, set the wrong subnet identifier. This should be + // rejected and this lease shouldn't be inserted into the database. + // Other leases should be inserted/updated just fine. + ++leases6_[1]->subnet_id_ = 0; + + // Modify the partner's lease cltt so it is earlier than the local lease. + // Therfore, this lease update should be rejected. + --leases6_[2]->cltt_; + + // Create HA configuration. + HAConfigPtr config_storage = createValidConfiguration(); + setBasicAuth(config_storage); + + // Convert leases to the JSON format, the same as used by the lease_cmds + // hook library. Configure our test HTTP servers to return those + // leases in this format. + ElementPtr response_arguments = Element::createMap(); + + // Leases are fetched in pages, so the lease4-get-page should be + // sent multiple times. We need to configure the server side to + // return leases in 3-element chunks. + createPagedSyncResponses6(); + + // Start the servers. + ASSERT_NO_THROW({ + listener_->start(); + listener2_->start(); + listener3_->start(); + }); + + TestHAService service(io_service_, network_state_, config_storage, + HAServerType::DHCPv6); + // Setting the heartbeat delay to 0 disables the recurring heartbeat. + // We just want to synchronize leases and not send the heartbeat. + config_storage->setHeartbeatDelay(0); + + // Start fetching leases asynchronously. + ASSERT_NO_THROW(service.asyncSyncLeases()); + + // Run IO service to actually perform the transaction. + ASSERT_NO_THROW(runIOService(TEST_TIMEOUT, []() { + // Stop running the IO service if we see a lease in the lease + // database which is expected to be inserted as a result of lease + // syncing. + return (!LeaseMgrFactory::instance().getLeases6(SubnetID(10)).empty()); + })); + + // Check if all leases have been stored in the local database. + for (size_t i = 0; i < leases6_.size(); ++i) { + if (i == 1) { + // This lease was purposely malformed and thus shouldn't be + // inserted into the database. + EXPECT_FALSE(LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, + leases6_[i]->addr_)) + << "lease " << leases6_[i]->addr_.toText() + << " was inserted into the database, but it shouldn't"; + } else { + // Other leases should be inserted/updated. + Lease6Ptr existing_lease = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, + leases6_[i]->addr_); + ASSERT_TRUE(existing_lease) << "lease " << leases6_[i]->addr_.toText() + << " not in the lease database"; + + if (i == 2) { + // The existing lease should have unmodified timestamp because the + // update is expected to be rejected. Same for valid lifetime. + EXPECT_LT(leases6_[i]->cltt_, existing_lease->cltt_); + EXPECT_NE(leases6_[i]->valid_lft_, existing_lease->valid_lft_); + + } else { + // All other leases should have the same cltt. + EXPECT_EQ(leases6_[i]->cltt_, existing_lease->cltt_); + + // Leases with even indexes were added to the database with modified + // valid lifetime. Thus the local copy of each such lease should have + // this modified valid lifetime. The lease #0 should be updated from + // the partner because of the partner's cltt was set to later time. + if ((i != 0) && (i % 2) == 0) { + EXPECT_EQ(leases6_[i]->valid_lft_ - 1, existing_lease->valid_lft_); + + } else { + // All other leases should have been fetched from the partner and + // inserted with no change. + EXPECT_EQ(leases6_[i]->valid_lft_, existing_lease->valid_lft_); + } + } + } + } +} + +// This test verifies that IPv6 leases can be fetched from the peer and inserted +// or updated in the local lease database. +TEST_F(HAServiceTest, asyncSyncLeases6Authorized) { + // Update config to provide authentication. + user2_ = "foo"; + password2_ = "bar"; + user3_ = "test"; + password3_ = "1234"; + + // Instruct servers to require authentication. + factory2_->getResponseCreator()->addBasicAuth("foo", "bar"); + factory3_->getResponseCreator()->addBasicAuth("test", "1234"); + + // Create lease manager. + ASSERT_NO_THROW(LeaseMgrFactory::create("universe=6 type=memfile persist=false")); + + // Create IPv6 leases which will be fetched from the other server. + ASSERT_NO_THROW(generateTestLeases6()); + + for (size_t i = 0; i < leases6_.size(); ++i) { + // For every even lease index we add this lease to the database to exercise + // the scenario when a lease is already in the database and may be updated + // by the lease synchronization procedure. + if ((i % 2) == 0) { + // Add a copy of the lease to make sure that by modifying the lease + // contents we don't affect the lease in the database. + Lease6Ptr lease_to_add(new Lease6(*leases6_[i])); + // Modify valid lifetime of the lease in the database so we can + // later use this value to verify if the lease has been updated. + --lease_to_add->valid_lft_; + LeaseMgrFactory::instance().addLease(lease_to_add); + } + } + + // Modify cltt of the first lease. This lease should be updated as a result + // of synchrnonization process because cltt is checked and the lease is + // updated if the cltt of the fetched lease is later than the cltt of the + // existing lease. + ++leases6_[0]->cltt_; + + // For the second lease, set the wrong subnet identifier. This should be + // rejected and this lease shouldn't be inserted into the database. + // Other leases should be inserted/updated just fine. + ++leases6_[1]->subnet_id_ = 0; + + // Modify the partner's lease cltt so it is earlier than the local lease. + // Therfore, this lease update should be rejected. + --leases6_[2]->cltt_; + + // Create HA configuration. + HAConfigPtr config_storage = createValidConfiguration(); + setBasicAuth(config_storage); + + // Convert leases to the JSON format, the same as used by the lease_cmds + // hook library. Configure our test HTTP servers to return those + // leases in this format. + ElementPtr response_arguments = Element::createMap(); + + // Leases are fetched in pages, so the lease4-get-page should be + // sent multiple times. We need to configure the server side to + // return leases in 3-element chunks. + createPagedSyncResponses6(); + + // Start the servers. + ASSERT_NO_THROW({ + listener_->start(); + listener2_->start(); + listener3_->start(); + }); + + TestHAService service(io_service_, network_state_, config_storage, + HAServerType::DHCPv6); + // Setting the heartbeat delay to 0 disables the recurring heartbeat. + // We just want to synchronize leases and not send the heartbeat. + config_storage->setHeartbeatDelay(0); + + // Start fetching leases asynchronously. + ASSERT_NO_THROW(service.asyncSyncLeases()); + + // Run IO service to actually perform the transaction. + ASSERT_NO_THROW(runIOService(TEST_TIMEOUT, []() { + // Stop running the IO service if we see a lease in the lease + // database which is expected to be inserted as a result of lease + // syncing. + return (!LeaseMgrFactory::instance().getLeases6(SubnetID(10)).empty()); + })); + + // Check if all leases have been stored in the local database. + for (size_t i = 0; i < leases6_.size(); ++i) { + if (i == 1) { + // This lease was purposely malformed and thus shouldn't be + // inserted into the database. + EXPECT_FALSE(LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, + leases6_[i]->addr_)) + << "lease " << leases6_[i]->addr_.toText() + << " was inserted into the database, but it shouldn't"; + } else { + // Other leases should be inserted/updated. + Lease6Ptr existing_lease = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, + leases6_[i]->addr_); + ASSERT_TRUE(existing_lease) << "lease " << leases6_[i]->addr_.toText() + << " not in the lease database"; + + if (i == 2) { + // The existing lease should have unmodified timestamp because the + // update is expected to be rejected. Same for valid lifetime. + EXPECT_LT(leases6_[i]->cltt_, existing_lease->cltt_); + EXPECT_NE(leases6_[i]->valid_lft_, existing_lease->valid_lft_); } else { // All other leases should have the same cltt. @@ -2256,6 +2853,44 @@ TEST_F(HAServiceTest, asyncSyncLeases6ServerOffline) { ASSERT_NO_THROW(runIOService(1000)); } +// Test that there is no exception thrown during IPv6 leases synchronization +// when server requires not provided authentication. +TEST_F(HAServiceTest, asyncSyncLeases6Unauthorized) { + // Instruct servers to require authentication. + factory2_->getResponseCreator()->addBasicAuth("foo", "bar"); + factory3_->getResponseCreator()->addBasicAuth("test", "1234"); + + // Create lease manager. + ASSERT_NO_THROW(LeaseMgrFactory::create("universe=6 type=memfile persist=false")); + + // Create IPv6 leases which will be fetched from the other server. + ASSERT_NO_THROW(generateTestLeases6()); + + // Create HA configuration. + HAConfigPtr config_storage = createValidConfiguration(); + setBasicAuth(config_storage); + + // Setting the heartbeat delay to 0 disables the recurring heartbeat. + // We just want to synchronize leases and not send the heartbeat. + config_storage->setHeartbeatDelay(0); + + // Start the servers. + ASSERT_NO_THROW({ + listener_->start(); + listener2_->start(); + listener3_->start(); + }); + + TestHAService service(io_service_, network_state_, config_storage, + HAServerType::DHCPv6); + + // Start fetching leases asynchronously. + ASSERT_NO_THROW(service.asyncSyncLeases()); + + // Run IO service to actually perform the transaction. + ASSERT_NO_THROW(runIOService(1000)); +} + // This test verifies that the ha-sync command is processed successfully for the // DHCPv4 server. TEST_F(HAServiceTest, processSynchronize4) { @@ -2283,6 +2918,42 @@ TEST_F(HAServiceTest, processSynchronize4) { EXPECT_TRUE(factory2_->getResponseCreator()->findRequest("dhcp-enable","")); } +// This test verifies that the ha-sync command is processed successfully for the +// DHCPv4 server. +TEST_F(HAServiceTest, processSynchronize4Authorized) { + // Update config to provide authentication. + user2_ = "foo"; + password2_ = "bar"; + user3_ = "test"; + password3_ = "1234"; + + // Instruct servers to require authentication. + factory2_->getResponseCreator()->addBasicAuth("foo", "bar"); + factory3_->getResponseCreator()->addBasicAuth("test", "1234"); + + // Run HAService::processSynchronize and gather a response. + ConstElementPtr rsp; + runProcessSynchronize4(rsp); + + // The response should indicate success. + ASSERT_TRUE(rsp); + checkAnswer(rsp, CONTROL_RESULT_SUCCESS, "Lease database synchronization" + " complete."); + + // All leases should have been inserted into the database. + for (size_t i = 0; i < leases4_.size(); ++i) { + Lease4Ptr existing_lease = LeaseMgrFactory::instance().getLease4(leases4_[i]->addr_); + ASSERT_TRUE(existing_lease) << "lease " << leases4_[i]->addr_.toText() + << " not in the lease database"; + } + + // The following commands should have been sent to the server2: dhcp-disable, + // lease4-get-page and dhcp-enable. + EXPECT_TRUE(factory2_->getResponseCreator()->findRequest("dhcp-disable","20")); + EXPECT_TRUE(factory2_->getResponseCreator()->findRequest("lease4-get-page","")); + EXPECT_TRUE(factory2_->getResponseCreator()->findRequest("dhcp-enable","")); +} + // This test verifies that an error is reported when sending a dhcp-disable // command causes an error. TEST_F(HAServiceTest, processSynchronizeDisableError) { @@ -2305,6 +2976,24 @@ TEST_F(HAServiceTest, processSynchronizeDisableError) { EXPECT_FALSE(factory2_->getResponseCreator()->findRequest("dhcp-enable","")); } +// This test verifies that an error is reported when sending any not +// authenticated command causes a not authorized error. +TEST_F(HAServiceTest, processSynchronizeUnauthorized) { + // Instruct server2 to require authentication. + factory2_->getResponseCreator()->addBasicAuth("foo", "bar"); + + // Run HAService::processSynchronize and gather a response. + ConstElementPtr rsp; + runProcessSynchronize4(rsp); + + // The response should indicate an error + ASSERT_TRUE(rsp); + checkAnswer(rsp, CONTROL_RESULT_ERROR); + + // The server2 should only receive dhcp-disable commands. + EXPECT_TRUE(factory2_->getResponseCreator()->getReceivedRequests().empty()); +} + // This test verifies that an error is reported when sending a lease4-get-page // command causes an error. TEST_F(HAServiceTest, processSynchronizeLease4GetPageError) { @@ -2376,6 +3065,43 @@ TEST_F(HAServiceTest, processSynchronize6) { EXPECT_TRUE(factory2_->getResponseCreator()->findRequest("dhcp-enable","")); } +// This test verifies that the ha-sync command is processed successfully for the +// DHCPv6 server. +TEST_F(HAServiceTest, processSynchronize6Authorized) { + // Update config to provide authentication. + user2_ = "foo"; + password2_ = "bar"; + user3_ = "test"; + password3_ = "1234"; + + // Instruct servers to require authentication. + factory2_->getResponseCreator()->addBasicAuth("foo", "bar"); + factory3_->getResponseCreator()->addBasicAuth("test", "1234"); + + // Run HAService::processSynchronize and gather a response. + ConstElementPtr rsp; + runProcessSynchronize6(rsp); + + // The response should indicate success. + ASSERT_TRUE(rsp); + checkAnswer(rsp, CONTROL_RESULT_SUCCESS, "Lease database synchronization" + " complete."); + + // All leases should have been inserted into the database. + for (size_t i = 0; i < leases6_.size(); ++i) { + Lease6Ptr existing_lease = LeaseMgrFactory::instance().getLease6(Lease::TYPE_NA, + leases6_[i]->addr_); + ASSERT_TRUE(existing_lease) << "lease " << leases6_[i]->addr_.toText() + << " not in the lease database"; + } + + // The following commands should have been sent to the server2: dhcp-disable, + // lease6-get-page and dhcp-enable. + EXPECT_TRUE(factory2_->getResponseCreator()->findRequest("dhcp-disable","20")); + EXPECT_TRUE(factory2_->getResponseCreator()->findRequest("lease6-get-page","")); + EXPECT_TRUE(factory2_->getResponseCreator()->findRequest("dhcp-enable","")); +} + // This test verifies that an error is reported when sending a dhcp-disable // command causes an error. TEST_F(HAServiceTest, processSynchronize6DisableError) { @@ -2398,6 +3124,24 @@ TEST_F(HAServiceTest, processSynchronize6DisableError) { EXPECT_FALSE(factory2_->getResponseCreator()->findRequest("dhcp-enable","")); } +// This test verifies that an error is reported when sending any not +// authenticated command causes a not authorized error. +TEST_F(HAServiceTest, processSynchronize6Unauthorized) { + // Instruct server2 to require authentication. + factory2_->getResponseCreator()->addBasicAuth("foo", "bar"); + + // Run HAService::processSynchronize and gather a response. + ConstElementPtr rsp; + runProcessSynchronize6(rsp); + + // The response should indicate an error + ASSERT_TRUE(rsp); + checkAnswer(rsp, CONTROL_RESULT_ERROR); + + // The server2 should only receive dhcp-disable commands. + EXPECT_TRUE(factory2_->getResponseCreator()->getReceivedRequests().empty()); +} + // This test verifies that an error is reported when sending a lease6-get-page // command causes an error. TEST_F(HAServiceTest, processSynchronizeLease6GetPageError) { @@ -2442,9 +3186,55 @@ TEST_F(HAServiceTest, processSynchronize6EnableError) { } // This test verifies that the DHCPv4 service can be disabled on the remote server. -TEST_F(HAServiceTest, asyncDisableDHCPService4) { +TEST_F(HAServiceTest, asyncDisableDHCPService4) { + // Create HA configuration. + HAConfigPtr config_storage = createValidConfiguration(); + setBasicAuth(config_storage); + + // Start the servers. + ASSERT_NO_THROW({ + listener_->start(); + listener2_->start(); + listener3_->start(); + }); + + TestHAService service(io_service_, network_state_, config_storage); + + // Send dhcp-disable command with max-period of 10 seconds. + // When the transaction is finished, the IO service gets stopped. + ASSERT_NO_THROW(service.asyncDisableDHCPService("server3", 10, + [this](const bool success, + const std::string& error_message) { + EXPECT_TRUE(success); + EXPECT_TRUE(error_message.empty()); + io_service_->stop(); + })); + + // Run IO service to actually perform the transaction. + ASSERT_NO_THROW(runIOService(TEST_TIMEOUT)); + + // The second server should not receive the command. + EXPECT_FALSE(factory2_->getResponseCreator()->findRequest("dhcp-disable","10")); + // The third server should receive the dhcp-disable command with the max-period + // value of 10. + EXPECT_TRUE(factory3_->getResponseCreator()->findRequest("dhcp-disable","10")); +} + +// This test verifies that the DHCPv4 service can be disabled on the remote server. +TEST_F(HAServiceTest, asyncDisableDHCPService4Authorized) { + // Update config to provide authentication. + user2_ = "foo"; + password2_ = "bar"; + user3_ = "test"; + password3_ = "1234"; + + // Instruct servers to require authentication. + factory2_->getResponseCreator()->addBasicAuth("foo", "bar"); + factory3_->getResponseCreator()->addBasicAuth("test", "1234"); + // Create HA configuration. HAConfigPtr config_storage = createValidConfiguration(); + setBasicAuth(config_storage); // Start the servers. ASSERT_NO_THROW({ @@ -2531,10 +3321,88 @@ TEST_F(HAServiceTest, asyncDisableDHCPService4ControlResultError) { ASSERT_NO_THROW(runIOService(TEST_TIMEOUT)); } +// This test verifies that an error is returned when the remote server +// requires not provided authentication. +TEST_F(HAServiceTest, asyncDisableDHCPService4ControlResultUnauthorized) { + // Instruct servers to require authentication. + factory2_->getResponseCreator()->addBasicAuth("foo", "bar"); + factory3_->getResponseCreator()->addBasicAuth("test", "1234"); + + // Create HA configuration. + HAConfigPtr config_storage = createValidConfiguration(); + + // Start the servers. + ASSERT_NO_THROW({ + listener_->start(); + listener2_->start(); + listener3_->start(); + }); + + TestHAService service(io_service_, network_state_, config_storage); + + // Send dhcp-disable command with max-period of 10 seconds. + // When the transaction is finished, the IO service gets stopped. + ASSERT_NO_THROW(service.asyncDisableDHCPService("server3", 10, + [this](const bool success, + const std::string& error_message) { + EXPECT_FALSE(success); + EXPECT_FALSE(error_message.empty()); + io_service_->stop(); + })); + + // Run IO service to actually perform the transaction. + ASSERT_NO_THROW(runIOService(TEST_TIMEOUT)); +} + // This test verifies that the DHCPv4 service can be enabled on the remote server. TEST_F(HAServiceTest, asyncEnableDHCPService4) { // Create HA configuration. HAConfigPtr config_storage = createValidConfiguration(); + setBasicAuth(config_storage); + + // Start the servers. + ASSERT_NO_THROW({ + listener_->start(); + listener2_->start(); + listener3_->start(); + }); + + TestHAService service(io_service_, network_state_, config_storage); + + // Send dhcp-enable command. When the transaction is finished, + // the IO service gets stopped. + ASSERT_NO_THROW(service.asyncEnableDHCPService("server2", + [this](const bool success, + const std::string& error_message) { + EXPECT_TRUE(success); + EXPECT_TRUE(error_message.empty()); + io_service_->stop(); + })); + + // Run IO service to actually perform the transaction. + ASSERT_NO_THROW(runIOService(TEST_TIMEOUT)); + + // The second server should receive the dhcp-enable. + EXPECT_TRUE(factory2_->getResponseCreator()->findRequest("dhcp-enable","")); + // The third server should not receive the command. + EXPECT_FALSE(factory3_->getResponseCreator()->findRequest("dhcp-enable","")); +} + +// This test verifies that the DHCPv4 service can be enabled on the remote server. +TEST_F(HAServiceTest, asyncEnableDHCPService4Authorized) { + // Update config to provide authentication. + user2_ = "foo"; + password2_ = "bar"; + user3_ = "test"; + password3_ = "1234"; + + // Instruct servers to require authentication. + factory2_->getResponseCreator()->addBasicAuth("foo", "bar"); + factory3_->getResponseCreator()->addBasicAuth("test", "1234"); + + // Create HA configuration. + HAConfigPtr config_storage = createValidConfiguration(); + setBasicAuth(config_storage); // Start the servers. ASSERT_NO_THROW({ @@ -2620,6 +3488,39 @@ TEST_F(HAServiceTest, asyncEnableDHCPService4ControlResultError) { ASSERT_NO_THROW(runIOService(TEST_TIMEOUT)); } +// This test verifies that an error is returned when the remote server +// requires not provided authentication. +TEST_F(HAServiceTest, asyncEnableDHCPService4ControlResultUnauthorized) { + // Instruct servers to require authentication. + factory2_->getResponseCreator()->addBasicAuth("foo", "bar"); + factory3_->getResponseCreator()->addBasicAuth("test", "1234"); + + // Create HA configuration. + HAConfigPtr config_storage = createValidConfiguration(); + + // Start the servers. + ASSERT_NO_THROW({ + listener_->start(); + listener2_->start(); + listener3_->start(); + }); + + TestHAService service(io_service_, network_state_, config_storage); + + // Send dhcp-enable command. When the transaction is finished, + // the IO service gets stopped. + ASSERT_NO_THROW(service.asyncEnableDHCPService("server2", + [this](const bool success, + const std::string& error_message) { + EXPECT_FALSE(success); + EXPECT_FALSE(error_message.empty()); + io_service_->stop(); + })); + + // Run IO service to actually perform the transaction. + ASSERT_NO_THROW(runIOService(TEST_TIMEOUT)); +} + // This test verifies that the "ha-scopes" command is processed correctly. TEST_F(HAServiceTest, processScopes) { // Create HA configuration. @@ -2785,6 +3686,59 @@ TEST_F(HAServiceTest, processMaintenanceStartSuccess) { // Create HA configuration for 3 servers. This server is // server 1. HAConfigPtr config_storage = createValidConfiguration(); + setBasicAuth(config_storage); + + // Start the servers. + ASSERT_NO_THROW({ + listener_->start(); + listener2_->start(); + }); + + HAService service(io_service_, network_state_, config_storage); + + // The tested function is synchronous, so we need to run server side IO service + // in background to not block the main thread. + auto thread = runIOServiceInThread(); + + // Process ha-maintenance-start command. + ConstElementPtr rsp; + ASSERT_NO_THROW(rsp = service.processMaintenanceStart()); + + // Stop the IO service. This should cause the thread to terminate. + io_service_->stop(); + thread->join(); + io_service_->get_io_service().reset(); + io_service_->poll(); + + // The partner of our server is online and should have responded with + // the success status. Therefore, this server should have transitioned + // to the partner-in-maintenance state. + ASSERT_TRUE(rsp); + checkAnswer(rsp, CONTROL_RESULT_SUCCESS, "Server is now in the partner-in-maintenance state" + " and its partner is in-maintenance state. The partner can be now safely" + " shut down."); + + EXPECT_EQ(HA_PARTNER_IN_MAINTENANCE_ST, service.getCurrState()); +} + +// This test verifies the case when the server receiving the ha-maintenance-start +// command successfully transitions to the partner-in-maintenance state and its +// partner transitions to the in-maintenance state. +TEST_F(HAServiceTest, processMaintenanceStartSuccessAuthorized) { + // Update config to provide authentication. + user2_ = "foo"; + password2_ = "bar"; + user3_ = "test"; + password3_ = "1234"; + + // Instruct servers to require authentication. + factory2_->getResponseCreator()->addBasicAuth("foo", "bar"); + factory3_->getResponseCreator()->addBasicAuth("test", "1234"); + + // Create HA configuration for 3 servers. This server is + // server 1. + HAConfigPtr config_storage = createValidConfiguration(); + setBasicAuth(config_storage); // Start the servers. ASSERT_NO_THROW({ @@ -2903,6 +3857,48 @@ TEST_F(HAServiceTest, processMaintenanceStartPartnerError) { EXPECT_EQ(HA_PARTNER_DOWN_ST, service.getCurrState()); } +// This test verifies the case when the server is receiving +// ha-maintenance-start command and tries to notify the partner +// which requires not provided authentication. +TEST_F(HAServiceTest, processMaintenanceStartPartnerUnauthorized) { + // Instruct servers to require authentication. + factory2_->getResponseCreator()->addBasicAuth("foo", "bar"); + factory3_->getResponseCreator()->addBasicAuth("test", "1234"); + + // Create HA configuration for 3 servers. This server is + // server 1. + HAConfigPtr config_storage = createValidConfiguration(); + + // Start the servers. + ASSERT_NO_THROW({ + listener_->start(); + listener2_->start(); + }); + + HAService service(io_service_, network_state_, config_storage); + + // The tested function is synchronous, so we need to run server side IO service + // in background to not block the main thread. + auto thread = runIOServiceInThread(); + + // Process ha-maintenance-start command. + ConstElementPtr rsp; + ASSERT_NO_THROW(rsp = service.processMaintenanceStart()); + + // Stop the IO service. This should cause the thread to terminate. + io_service_->stop(); + thread->join(); + io_service_->get_io_service().reset(); + io_service_->poll(); + + ASSERT_TRUE(rsp); + checkAnswer(rsp, CONTROL_RESULT_SUCCESS, + "Server is now in the partner-down state as its" + " partner appears to be offline for maintenance."); + + EXPECT_EQ(HA_PARTNER_DOWN_ST, service.getCurrState()); +} + // This test verifies the case when the server is receiving // ha-maintenance-start command and tries to notify the partner // which returns a special result indicating that it can't enter @@ -2956,6 +3952,58 @@ TEST_F(HAServiceTest, processMaintenanceCancelSuccess) { // Create HA configuration for 3 servers. This server is // server 1. HAConfigPtr config_storage = createValidConfiguration(); + setBasicAuth(config_storage); + + // Start the servers. + ASSERT_NO_THROW({ + listener_->start(); + listener2_->start(); + }); + + TestHAService service(io_service_, network_state_, config_storage); + + ASSERT_NO_THROW(service.verboseTransition(HA_PARTNER_IN_MAINTENANCE_ST)); + + // The tested function is synchronous, so we need to run server side IO service + // in background to not block the main thread. + auto thread = runIOServiceInThread(); + + // Process ha-maintenance-cancel command. + ConstElementPtr rsp; + ASSERT_NO_THROW(rsp = service.processMaintenanceCancel()); + + // Stop the IO service. This should cause the thread to terminate. + io_service_->stop(); + thread->join(); + io_service_->get_io_service().reset(); + io_service_->poll(); + + // The partner of our server is online and should have responded with + // the success status. Therefore, this server should have transitioned + // to the partner-in-maintenance state. + ASSERT_TRUE(rsp); + checkAnswer(rsp, CONTROL_RESULT_SUCCESS, "Server maintenance successfully canceled."); + + EXPECT_EQ(HA_WAITING_ST, service.getCurrState()); +} + +// This test verifies the case when the server receiving the ha-maintenance-cancel +// command successfully transitions out of the partner-in-maintenance state. +TEST_F(HAServiceTest, processMaintenanceCancelSuccessAuthorized) { + // Update config to provide authentication. + user2_ = "foo"; + password2_ = "bar"; + user3_ = "test"; + password3_ = "1234"; + + // Instruct servers to require authentication. + factory2_->getResponseCreator()->addBasicAuth("foo", "bar"); + factory3_->getResponseCreator()->addBasicAuth("test", "1234"); + + // Create HA configuration for 3 servers. This server is + // server 1. + HAConfigPtr config_storage = createValidConfiguration(); + setBasicAuth(config_storage); // Start the servers. ASSERT_NO_THROW({ @@ -3035,6 +4083,52 @@ TEST_F(HAServiceTest, processMaintenanceCancelPartnerError) { EXPECT_EQ(HA_PARTNER_IN_MAINTENANCE_ST, service.getCurrState()); } +// This test verifies that the maintenance is not canceled in case the +// partner requires not provided authentication. +TEST_F(HAServiceTest, processMaintenanceCancelPartnerUnauthorized) { + // Instruct servers to require authentication. + factory2_->getResponseCreator()->addBasicAuth("foo", "bar"); + factory3_->getResponseCreator()->addBasicAuth("test", "1234"); + + // Create HA configuration for 3 servers. This server is + // server 1. + HAConfigPtr config_storage = createValidConfiguration(); + + // Start the servers. + ASSERT_NO_THROW({ + listener_->start(); + listener2_->start(); + }); + + TestHAService service(io_service_, network_state_, config_storage); + + ASSERT_NO_THROW(service.verboseTransition(HA_PARTNER_IN_MAINTENANCE_ST)); + + // The tested function is synchronous, so we need to run server side IO service + // in background to not block the main thread. + auto thread = runIOServiceInThread(); + + // Process ha-maintenance-cancel command. + ConstElementPtr rsp; + ASSERT_NO_THROW(rsp = service.processMaintenanceCancel()); + + // Stop the IO service. This should cause the thread to terminate. + io_service_->stop(); + thread->join(); + io_service_->get_io_service().reset(); + io_service_->poll(); + + // The partner should have responded with an error. + ASSERT_TRUE(rsp); + checkAnswer(rsp, CONTROL_RESULT_ERROR, + "Unable to cancel maintenance. The partner server responded" + " with the following message to the ha-maintenance-notify" + " commmand: Unauthorized, error code 1."); + + // The state of this server should not change. + EXPECT_EQ(HA_PARTNER_IN_MAINTENANCE_ST, service.getCurrState()); +} + /// @brief HA partner to the server under test. /// -- GitLab From 091b84de57eb92a3f5eafccaa512b20052915a20 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Tue, 14 Jul 2020 20:30:23 +0200 Subject: [PATCH 16/33] [#1304] Updated .gitignore --- src/bin/shell/tests/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bin/shell/tests/.gitignore b/src/bin/shell/tests/.gitignore index ed32d08a60..e2028da576 100644 --- a/src/bin/shell/tests/.gitignore +++ b/src/bin/shell/tests/.gitignore @@ -1,2 +1,3 @@ +/basic_auth_tests.sh /shell_process_tests.sh /shell_unittest.py -- GitLab From 45bac04fbe921bed64095844a8f520664cf2c8ac Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Tue, 28 Jul 2020 15:02:20 +0200 Subject: [PATCH 17/33] [#1304] Addressed comments --- doc/examples/agent/comments.json | 2 +- doc/sphinx/arm/agent.rst | 2 +- src/hooks/dhcp/high_availability/ha_config.h | 3 ++- src/lib/http/basic_auth.h | 9 +++++---- src/lib/http/http_messages.mes | 3 ++- src/lib/http/response_creator_auth.h | 2 +- 6 files changed, 12 insertions(+), 9 deletions(-) diff --git a/doc/examples/agent/comments.json b/doc/examples/agent/comments.json index d0c6a00285..afa706e27c 100644 --- a/doc/examples/agent/comments.json +++ b/doc/examples/agent/comments.json @@ -12,7 +12,7 @@ "http-port": 8000, "basic-authentication-realm": "kea-control-agent", - // In basoc HTTP authentication + // In basic HTTP authentication "basic-authentications": [ { diff --git a/doc/sphinx/arm/agent.rst b/doc/sphinx/arm/agent.rst index 37c215a12a..d2f26693a0 100644 --- a/doc/sphinx/arm/agent.rst +++ b/doc/sphinx/arm/agent.rst @@ -138,7 +138,7 @@ ability to store comments or descriptions; the parser translates a comment to be attached within the configuration itself. The basic HTTP authentication was added by Kea 1.7.10. It protects -not authorized uses of the control agent by local users. For the +against not authorized uses of the control agent by local users. For the protection against remote attackers HTTPS and reverse proxy of :ref:`agent-secure-connection` provide a stronger security. diff --git a/src/hooks/dhcp/high_availability/ha_config.h b/src/hooks/dhcp/high_availability/ha_config.h index 95c81b47c9..84c15d9063 100644 --- a/src/hooks/dhcp/high_availability/ha_config.h +++ b/src/hooks/dhcp/high_availability/ha_config.h @@ -160,7 +160,8 @@ public: return (basic_auth_); } - /// @brief Adds a basic HTTP authentication header to a request. + /// @brief Adds a basic HTTP authentication header to a request + /// when credentials are specified. void addBasicAuthHttpHeader(http::PostHttpRequestJsonPtr request) const; private: diff --git a/src/lib/http/basic_auth.h b/src/lib/http/basic_auth.h index 3968e56de1..d939cdb451 100644 --- a/src/lib/http/basic_auth.h +++ b/src/lib/http/basic_auth.h @@ -52,16 +52,17 @@ private: /// @brief Build the credential from the secret. void buildCredential(); - /// @brief User id. + /// @brief User id e.g. johndoe. std::string user_; - /// @brief Password. + /// @brief Password e.g. secret1. std::string password_; - /// @brief Secret. + /// @brief Secret e.g. johndoe:secret1. std::string secret_; - /// @brief Credential. + /// @brief Credential: base64 encoding of UTF-8 secret, + /// e.g. am9obmRvZTpzZWNyZXQx. std::string credential_; }; diff --git a/src/lib/http/http_messages.mes b/src/lib/http/http_messages.mes index cbd173fb5c..c171b96d66 100644 --- a/src/lib/http/http_messages.mes +++ b/src/lib/http/http_messages.mes @@ -43,7 +43,8 @@ a malformed authentication header. The argument explains the problem. % HTTP_CLIENT_REQUEST_NOT_AUTHORIZED received HTTP request with not matching authentication header This information message is issued when the server receives a request with -authentication header carrying not recognized credential. +authentication header carrying not recognized credential: the user +provided incorrect user id and/or password. % HTTP_CLIENT_REQUEST_NO_AUTH_HEADER received HTTP request without required authentication header This information message is issued when the server receives a request without diff --git a/src/lib/http/response_creator_auth.h b/src/lib/http/response_creator_auth.h index 1b5462dbe3..830b335f6b 100644 --- a/src/lib/http/response_creator_auth.h +++ b/src/lib/http/response_creator_auth.h @@ -20,7 +20,7 @@ namespace http { /// /// @param creator The HTTP response creator. /// @param request The HTTP request to validate. -/// @param credentials Authorized credentials and user id map. +/// @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, -- GitLab From 6ca8130be1a2246bb2db61b16cf0cd20798a2854 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Tue, 28 Jul 2020 15:17:07 +0200 Subject: [PATCH 18/33] [#1304] Regen http message files --- src/lib/http/http_messages.cc | 2 +- src/lib/http/http_messages.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/http/http_messages.cc b/src/lib/http/http_messages.cc index 73068a1a80..70ec76b86c 100644 --- a/src/lib/http/http_messages.cc +++ b/src/lib/http/http_messages.cc @@ -1,4 +1,4 @@ -// File created from ../../../src/lib/http/http_messages.mes on Sun Jul 12 2020 02:08 +// File created from ../../../src/lib/http/http_messages.mes on Tue Jul 28 2020 15:04 #include #include diff --git a/src/lib/http/http_messages.h b/src/lib/http/http_messages.h index 91d5392dfd..5fedfc6125 100644 --- a/src/lib/http/http_messages.h +++ b/src/lib/http/http_messages.h @@ -1,4 +1,4 @@ -// File created from ../../../src/lib/http/http_messages.mes on Sun Jul 12 2020 02:08 +// File created from ../../../src/lib/http/http_messages.mes on Tue Jul 28 2020 15:04 #ifndef HTTP_MESSAGES_H #define HTTP_MESSAGES_H -- GitLab From f3ed57a5ed26c7fa38e015d3871b39bca32900f3 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Tue, 28 Jul 2020 16:26:42 +0200 Subject: [PATCH 19/33] [#1304] Prepared server callout --- src/bin/agent/ca_response_creator.cc | 9 +-- src/lib/http/response_creator_auth.cc | 25 ++++-- src/lib/http/response_creator_auth.h | 14 ++-- .../http/tests/response_creator_unittests.cc | 80 ++++++++++++------- 4 files changed, 79 insertions(+), 49 deletions(-) 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 " -- GitLab From 4d7289cb42affd60b1776f5f8ecf55155d588a18 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Sat, 12 Sep 2020 08:52:33 +0000 Subject: [PATCH 20/33] [#1304] regen bison --- src/bin/agent/agent_parser.cc | 424 +++++++++++++++++----------------- src/bin/agent/agent_parser.h | 74 +++--- src/bin/agent/location.hh | 4 +- src/bin/agent/position.hh | 4 +- src/bin/agent/stack.hh | 4 +- 5 files changed, 254 insertions(+), 256 deletions(-) diff --git a/src/bin/agent/agent_parser.cc b/src/bin/agent/agent_parser.cc index 1f26b881e4..44a2f86c7a 100644 --- a/src/bin/agent/agent_parser.cc +++ b/src/bin/agent/agent_parser.cc @@ -1,4 +1,4 @@ -// A Bison parser, made by GNU Bison 3.6.4. +// A Bison parser, made by GNU Bison 3.7.2. // Skeleton implementation for Bison LALR(1) parsers in C++ @@ -209,25 +209,25 @@ namespace isc { namespace agent { { switch (that.kind ()) { - case 54: // value - case 57: // map_value - case 110: // socket_type_value + case symbol_kind::S_value: // value + case symbol_kind::S_map_value: // map_value + case symbol_kind::S_socket_type_value: // socket_type_value value.YY_MOVE_OR_COPY< ElementPtr > (YY_MOVE (that.value)); break; - case 45: // "boolean" + case symbol_kind::S_BOOLEAN: // "boolean" value.YY_MOVE_OR_COPY< bool > (YY_MOVE (that.value)); break; - case 44: // "floating point" + case symbol_kind::S_FLOAT: // "floating point" value.YY_MOVE_OR_COPY< double > (YY_MOVE (that.value)); break; - case 43: // "integer" + case symbol_kind::S_INTEGER: // "integer" value.YY_MOVE_OR_COPY< int64_t > (YY_MOVE (that.value)); break; - case 42: // "constant string" + case symbol_kind::S_STRING: // "constant string" value.YY_MOVE_OR_COPY< std::string > (YY_MOVE (that.value)); break; @@ -246,25 +246,25 @@ namespace isc { namespace agent { { switch (that.kind ()) { - case 54: // value - case 57: // map_value - case 110: // socket_type_value + case symbol_kind::S_value: // value + case symbol_kind::S_map_value: // map_value + case symbol_kind::S_socket_type_value: // socket_type_value value.move< ElementPtr > (YY_MOVE (that.value)); break; - case 45: // "boolean" + case symbol_kind::S_BOOLEAN: // "boolean" value.move< bool > (YY_MOVE (that.value)); break; - case 44: // "floating point" + case symbol_kind::S_FLOAT: // "floating point" value.move< double > (YY_MOVE (that.value)); break; - case 43: // "integer" + case symbol_kind::S_INTEGER: // "integer" value.move< int64_t > (YY_MOVE (that.value)); break; - case 42: // "constant string" + case symbol_kind::S_STRING: // "constant string" value.move< std::string > (YY_MOVE (that.value)); break; @@ -283,25 +283,25 @@ namespace isc { namespace agent { state = that.state; switch (that.kind ()) { - case 54: // value - case 57: // map_value - case 110: // socket_type_value + case symbol_kind::S_value: // value + case symbol_kind::S_map_value: // map_value + case symbol_kind::S_socket_type_value: // socket_type_value value.copy< ElementPtr > (that.value); break; - case 45: // "boolean" + case symbol_kind::S_BOOLEAN: // "boolean" value.copy< bool > (that.value); break; - case 44: // "floating point" + case symbol_kind::S_FLOAT: // "floating point" value.copy< double > (that.value); break; - case 43: // "integer" + case symbol_kind::S_INTEGER: // "integer" value.copy< int64_t > (that.value); break; - case 42: // "constant string" + case symbol_kind::S_STRING: // "constant string" value.copy< std::string > (that.value); break; @@ -319,25 +319,25 @@ namespace isc { namespace agent { state = that.state; switch (that.kind ()) { - case 54: // value - case 57: // map_value - case 110: // socket_type_value + case symbol_kind::S_value: // value + case symbol_kind::S_map_value: // map_value + case symbol_kind::S_socket_type_value: // socket_type_value value.move< ElementPtr > (that.value); break; - case 45: // "boolean" + case symbol_kind::S_BOOLEAN: // "boolean" value.move< bool > (that.value); break; - case 44: // "floating point" + case symbol_kind::S_FLOAT: // "floating point" value.move< double > (that.value); break; - case 43: // "integer" + case symbol_kind::S_INTEGER: // "integer" value.move< int64_t > (that.value); break; - case 42: // "constant string" + case symbol_kind::S_STRING: // "constant string" value.move< std::string > (that.value); break; @@ -377,43 +377,43 @@ namespace isc { namespace agent { << yysym.location << ": "; switch (yykind) { - case 42: // "constant string" + case symbol_kind::S_STRING: // "constant string" #line 104 "agent_parser.yy" { yyoutput << yysym.value.template as < std::string > (); } #line 384 "agent_parser.cc" break; - case 43: // "integer" + case symbol_kind::S_INTEGER: // "integer" #line 104 "agent_parser.yy" { yyoutput << yysym.value.template as < int64_t > (); } #line 390 "agent_parser.cc" break; - case 44: // "floating point" + case symbol_kind::S_FLOAT: // "floating point" #line 104 "agent_parser.yy" { yyoutput << yysym.value.template as < double > (); } #line 396 "agent_parser.cc" break; - case 45: // "boolean" + case symbol_kind::S_BOOLEAN: // "boolean" #line 104 "agent_parser.yy" { yyoutput << yysym.value.template as < bool > (); } #line 402 "agent_parser.cc" break; - case 54: // value + case symbol_kind::S_value: // value #line 104 "agent_parser.yy" { yyoutput << yysym.value.template as < ElementPtr > (); } #line 408 "agent_parser.cc" break; - case 57: // map_value + case symbol_kind::S_map_value: // map_value #line 104 "agent_parser.yy" { yyoutput << yysym.value.template as < ElementPtr > (); } #line 414 "agent_parser.cc" break; - case 110: // socket_type_value + case symbol_kind::S_socket_type_value: // socket_type_value #line 104 "agent_parser.yy" { yyoutput << yysym.value.template as < ElementPtr > (); } #line 420 "agent_parser.cc" @@ -646,25 +646,25 @@ namespace isc { namespace agent { when using variants. */ switch (yyr1_[yyn]) { - case 54: // value - case 57: // map_value - case 110: // socket_type_value + case symbol_kind::S_value: // value + case symbol_kind::S_map_value: // map_value + case symbol_kind::S_socket_type_value: // socket_type_value yylhs.value.emplace< ElementPtr > (); break; - case 45: // "boolean" + case symbol_kind::S_BOOLEAN: // "boolean" yylhs.value.emplace< bool > (); break; - case 44: // "floating point" + case symbol_kind::S_FLOAT: // "floating point" yylhs.value.emplace< double > (); break; - case 43: // "integer" + case symbol_kind::S_INTEGER: // "integer" yylhs.value.emplace< int64_t > (); break; - case 42: // "constant string" + case symbol_kind::S_STRING: // "constant string" yylhs.value.emplace< std::string > (); break; @@ -688,25 +688,25 @@ namespace isc { namespace agent { { switch (yyn) { - case 2: + case 2: // $@1: %empty #line 115 "agent_parser.yy" { ctx.ctx_ = ctx.NO_KEYWORDS; } #line 695 "agent_parser.cc" break; - case 4: + case 4: // $@2: %empty #line 116 "agent_parser.yy" { ctx.ctx_ = ctx.CONFIG; } #line 701 "agent_parser.cc" break; - case 6: + case 6: // $@3: %empty #line 117 "agent_parser.yy" { ctx.ctx_ = ctx.AGENT; } #line 707 "agent_parser.cc" break; - case 8: + case 8: // $@4: %empty #line 125 "agent_parser.yy" { // Parse the Control-agent map @@ -716,7 +716,7 @@ namespace isc { namespace agent { #line 717 "agent_parser.cc" break; - case 9: + case 9: // sub_agent: "{" $@4 global_params "}" #line 129 "agent_parser.yy" { // parsing completed @@ -724,7 +724,7 @@ namespace isc { namespace agent { #line 725 "agent_parser.cc" break; - case 10: + case 10: // json: value #line 136 "agent_parser.yy" { // Push back the JSON value on the stack @@ -733,49 +733,49 @@ namespace isc { namespace agent { #line 734 "agent_parser.cc" break; - case 11: + case 11: // value: "integer" #line 142 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ElementPtr(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location))); } #line 740 "agent_parser.cc" break; - case 12: + case 12: // value: "floating point" #line 143 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ElementPtr(new DoubleElement(yystack_[0].value.as < double > (), ctx.loc2pos(yystack_[0].location))); } #line 746 "agent_parser.cc" break; - case 13: + case 13: // value: "boolean" #line 144 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ElementPtr(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location))); } #line 752 "agent_parser.cc" break; - case 14: + case 14: // value: "constant string" #line 145 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); } #line 758 "agent_parser.cc" break; - case 15: + case 15: // value: "null" #line 146 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ElementPtr(new NullElement(ctx.loc2pos(yystack_[0].location))); } #line 764 "agent_parser.cc" break; - case 16: + case 16: // value: map #line 147 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ctx.stack_.back(); ctx.stack_.pop_back(); } #line 770 "agent_parser.cc" break; - case 17: + case 17: // value: list_generic #line 148 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ctx.stack_.back(); ctx.stack_.pop_back(); } #line 776 "agent_parser.cc" break; - case 18: + case 18: // $@5: %empty #line 152 "agent_parser.yy" { // This code is executed when we're about to start parsing @@ -786,7 +786,7 @@ namespace isc { namespace agent { #line 787 "agent_parser.cc" break; - case 19: + case 19: // map: "{" $@5 map_content "}" #line 157 "agent_parser.yy" { // map parsing completed. If we ever want to do any wrap up @@ -796,13 +796,13 @@ namespace isc { namespace agent { #line 797 "agent_parser.cc" break; - case 20: + case 20: // map_value: map #line 163 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ctx.stack_.back(); ctx.stack_.pop_back(); } #line 803 "agent_parser.cc" break; - case 23: + case 23: // not_empty_map: "constant string" ":" value #line 177 "agent_parser.yy" { // map containing a single entry @@ -811,7 +811,7 @@ namespace isc { namespace agent { #line 812 "agent_parser.cc" break; - case 24: + case 24: // not_empty_map: not_empty_map "," "constant string" ":" value #line 181 "agent_parser.yy" { // map consisting of a shorter map followed by @@ -821,7 +821,7 @@ namespace isc { namespace agent { #line 822 "agent_parser.cc" break; - case 25: + case 25: // $@6: %empty #line 188 "agent_parser.yy" { ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location))); @@ -830,14 +830,14 @@ namespace isc { namespace agent { #line 831 "agent_parser.cc" break; - case 26: + case 26: // list_generic: "[" $@6 list_content "]" #line 191 "agent_parser.yy" { } #line 838 "agent_parser.cc" break; - case 29: + case 29: // not_empty_list: value #line 198 "agent_parser.yy" { // List consisting of a single element. @@ -846,7 +846,7 @@ namespace isc { namespace agent { #line 847 "agent_parser.cc" break; - case 30: + case 30: // not_empty_list: not_empty_list "," value #line 202 "agent_parser.yy" { // List ending with , and a value. @@ -855,7 +855,7 @@ namespace isc { namespace agent { #line 856 "agent_parser.cc" break; - case 31: + case 31: // unknown_map_entry: "constant string" ":" #line 215 "agent_parser.yy" { const std::string& where = ctx.contextName(); @@ -866,7 +866,7 @@ namespace isc { namespace agent { #line 867 "agent_parser.cc" break; - case 32: + case 32: // $@7: %empty #line 223 "agent_parser.yy" { // This code is executed when we're about to start parsing @@ -877,7 +877,7 @@ namespace isc { namespace agent { #line 878 "agent_parser.cc" break; - case 33: + case 33: // agent_syntax_map: "{" $@7 global_objects "}" #line 228 "agent_parser.yy" { // map parsing completed. If we ever want to do any wrap up @@ -887,7 +887,7 @@ namespace isc { namespace agent { #line 888 "agent_parser.cc" break; - case 36: + case 36: // $@8: %empty #line 243 "agent_parser.yy" { @@ -903,7 +903,7 @@ namespace isc { namespace agent { #line 904 "agent_parser.cc" break; - case 37: + case 37: // agent_object: "Control-agent" $@8 ":" "{" global_params "}" #line 253 "agent_parser.yy" { // Ok, we're done with parsing control-agent. Let's take the map @@ -914,7 +914,7 @@ namespace isc { namespace agent { #line 915 "agent_parser.cc" break; - case 50: + case 50: // $@9: %empty #line 278 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); @@ -922,7 +922,7 @@ namespace isc { namespace agent { #line 923 "agent_parser.cc" break; - case 51: + case 51: // http_host: "http-host" $@9 ":" "constant string" #line 280 "agent_parser.yy" { ElementPtr host(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); @@ -932,7 +932,7 @@ namespace isc { namespace agent { #line 933 "agent_parser.cc" break; - case 52: + case 52: // http_port: "http-port" ":" "integer" #line 286 "agent_parser.yy" { ElementPtr prf(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location))); @@ -941,7 +941,7 @@ namespace isc { namespace agent { #line 942 "agent_parser.cc" break; - case 53: + case 53: // $@10: %empty #line 291 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); @@ -949,7 +949,7 @@ namespace isc { namespace agent { #line 950 "agent_parser.cc" break; - case 54: + case 54: // basic_authentication_realm: "basic-authentication-realm" $@10 ":" "constant string" #line 293 "agent_parser.yy" { ElementPtr realm(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); @@ -959,7 +959,7 @@ namespace isc { namespace agent { #line 960 "agent_parser.cc" break; - case 55: + case 55: // $@11: %empty #line 299 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); @@ -967,7 +967,7 @@ namespace isc { namespace agent { #line 968 "agent_parser.cc" break; - case 56: + case 56: // user_context: "user-context" $@11 ":" map_value #line 301 "agent_parser.yy" { ElementPtr parent = ctx.stack_.back(); @@ -994,7 +994,7 @@ namespace isc { namespace agent { #line 995 "agent_parser.cc" break; - case 57: + case 57: // $@12: %empty #line 324 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); @@ -1002,7 +1002,7 @@ namespace isc { namespace agent { #line 1003 "agent_parser.cc" break; - case 58: + case 58: // comment: "comment" $@12 ":" "constant string" #line 326 "agent_parser.yy" { ElementPtr parent = ctx.stack_.back(); @@ -1031,7 +1031,7 @@ namespace isc { namespace agent { #line 1032 "agent_parser.cc" break; - case 59: + case 59: // $@13: %empty #line 352 "agent_parser.yy" { ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location))); @@ -1042,7 +1042,7 @@ namespace isc { namespace agent { #line 1043 "agent_parser.cc" break; - case 60: + case 60: // hooks_libraries: "hooks-libraries" $@13 ":" "[" hooks_libraries_list "]" #line 357 "agent_parser.yy" { ctx.stack_.pop_back(); @@ -1051,7 +1051,7 @@ namespace isc { namespace agent { #line 1052 "agent_parser.cc" break; - case 65: + case 65: // $@14: %empty #line 370 "agent_parser.yy" { ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location))); @@ -1061,7 +1061,7 @@ namespace isc { namespace agent { #line 1062 "agent_parser.cc" break; - case 66: + case 66: // hooks_library: "{" $@14 hooks_params "}" #line 374 "agent_parser.yy" { ctx.stack_.pop_back(); @@ -1069,7 +1069,7 @@ namespace isc { namespace agent { #line 1070 "agent_parser.cc" break; - case 72: + case 72: // $@15: %empty #line 387 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); @@ -1077,7 +1077,7 @@ namespace isc { namespace agent { #line 1078 "agent_parser.cc" break; - case 73: + case 73: // library: "library" $@15 ":" "constant string" #line 389 "agent_parser.yy" { ElementPtr lib(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); @@ -1087,7 +1087,7 @@ namespace isc { namespace agent { #line 1088 "agent_parser.cc" break; - case 74: + case 74: // $@16: %empty #line 395 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); @@ -1095,16 +1095,16 @@ namespace isc { namespace agent { #line 1096 "agent_parser.cc" break; - case 75: + case 75: // parameters: "parameters" $@16 ":" map_value #line 397 "agent_parser.yy" - { + { ctx.stack_.back()->set("parameters", yystack_[0].value.as < ElementPtr > ()); ctx.leave(); } #line 1105 "agent_parser.cc" break; - case 76: + case 76: // $@17: %empty #line 405 "agent_parser.yy" { ElementPtr m(new MapElement(ctx.loc2pos(yystack_[2].location))); @@ -1115,7 +1115,7 @@ namespace isc { namespace agent { #line 1116 "agent_parser.cc" break; - case 77: + case 77: // control_sockets: "control-sockets" ":" "{" $@17 control_sockets_params "}" #line 410 "agent_parser.yy" { ctx.stack_.pop_back(); @@ -1124,7 +1124,7 @@ namespace isc { namespace agent { #line 1125 "agent_parser.cc" break; - case 84: + case 84: // $@18: %empty #line 431 "agent_parser.yy" { ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location))); @@ -1135,7 +1135,7 @@ namespace isc { namespace agent { #line 1136 "agent_parser.cc" break; - case 85: + case 85: // dhcp4_server_socket: "dhcp4" $@18 ":" "{" control_socket_params "}" #line 436 "agent_parser.yy" { ctx.stack_.pop_back(); @@ -1144,7 +1144,7 @@ namespace isc { namespace agent { #line 1145 "agent_parser.cc" break; - case 86: + case 86: // $@19: %empty #line 442 "agent_parser.yy" { ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location))); @@ -1155,7 +1155,7 @@ namespace isc { namespace agent { #line 1156 "agent_parser.cc" break; - case 87: + case 87: // dhcp6_server_socket: "dhcp6" $@19 ":" "{" control_socket_params "}" #line 447 "agent_parser.yy" { ctx.stack_.pop_back(); @@ -1164,7 +1164,7 @@ namespace isc { namespace agent { #line 1165 "agent_parser.cc" break; - case 88: + case 88: // $@20: %empty #line 453 "agent_parser.yy" { ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location))); @@ -1175,7 +1175,7 @@ namespace isc { namespace agent { #line 1176 "agent_parser.cc" break; - case 89: + case 89: // d2_server_socket: "d2" $@20 ":" "{" control_socket_params "}" #line 458 "agent_parser.yy" { ctx.stack_.pop_back(); @@ -1184,7 +1184,7 @@ namespace isc { namespace agent { #line 1185 "agent_parser.cc" break; - case 97: + case 97: // $@21: %empty #line 477 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); @@ -1192,7 +1192,7 @@ namespace isc { namespace agent { #line 1193 "agent_parser.cc" break; - case 98: + case 98: // socket_name: "socket-name" $@21 ":" "constant string" #line 479 "agent_parser.yy" { ElementPtr name(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); @@ -1202,7 +1202,7 @@ namespace isc { namespace agent { #line 1203 "agent_parser.cc" break; - case 99: + case 99: // $@22: %empty #line 486 "agent_parser.yy" { ctx.enter(ctx.SOCKET_TYPE); @@ -1210,7 +1210,7 @@ namespace isc { namespace agent { #line 1211 "agent_parser.cc" break; - case 100: + case 100: // socket_type: "socket-type" $@22 ":" socket_type_value #line 488 "agent_parser.yy" { ctx.stack_.back()->set("socket-type", yystack_[0].value.as < ElementPtr > ()); @@ -1219,13 +1219,13 @@ namespace isc { namespace agent { #line 1220 "agent_parser.cc" break; - case 101: + case 101: // socket_type_value: "unix" #line 494 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement("unix", ctx.loc2pos(yystack_[0].location))); } #line 1226 "agent_parser.cc" break; - case 102: + case 102: // $@23: %empty #line 501 "agent_parser.yy" { ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location))); @@ -1236,7 +1236,7 @@ namespace isc { namespace agent { #line 1237 "agent_parser.cc" break; - case 103: + case 103: // basic_authentications: "basic-authentications" $@23 ":" "[" basic_auth_list "]" #line 506 "agent_parser.yy" { ctx.stack_.pop_back(); @@ -1245,7 +1245,7 @@ namespace isc { namespace agent { #line 1246 "agent_parser.cc" break; - case 108: + case 108: // $@24: %empty #line 519 "agent_parser.yy" { ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location))); @@ -1255,7 +1255,7 @@ namespace isc { namespace agent { #line 1256 "agent_parser.cc" break; - case 109: + case 109: // basic_auth: "{" $@24 basic_auth_params "}" #line 523 "agent_parser.yy" { ctx.stack_.pop_back(); @@ -1263,7 +1263,7 @@ namespace isc { namespace agent { #line 1264 "agent_parser.cc" break; - case 117: + case 117: // $@25: %empty #line 538 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); @@ -1271,7 +1271,7 @@ namespace isc { namespace agent { #line 1272 "agent_parser.cc" break; - case 118: + case 118: // user: "user" $@25 ":" "constant string" #line 540 "agent_parser.yy" { ElementPtr user(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); @@ -1281,7 +1281,7 @@ namespace isc { namespace agent { #line 1282 "agent_parser.cc" break; - case 119: + case 119: // $@26: %empty #line 546 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); @@ -1289,7 +1289,7 @@ namespace isc { namespace agent { #line 1290 "agent_parser.cc" break; - case 120: + case 120: // password: "password" $@26 ":" "constant string" #line 548 "agent_parser.yy" { ElementPtr password(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); @@ -1299,7 +1299,7 @@ namespace isc { namespace agent { #line 1300 "agent_parser.cc" break; - case 121: + case 121: // $@27: %empty #line 558 "agent_parser.yy" { ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location))); @@ -1310,7 +1310,7 @@ namespace isc { namespace agent { #line 1311 "agent_parser.cc" break; - case 122: + case 122: // loggers: "loggers" $@27 ":" "[" loggers_entries "]" #line 563 "agent_parser.yy" { ctx.stack_.pop_back(); @@ -1319,7 +1319,7 @@ namespace isc { namespace agent { #line 1320 "agent_parser.cc" break; - case 125: + case 125: // $@28: %empty #line 575 "agent_parser.yy" { ElementPtr l(new MapElement(ctx.loc2pos(yystack_[0].location))); @@ -1329,7 +1329,7 @@ namespace isc { namespace agent { #line 1330 "agent_parser.cc" break; - case 126: + case 126: // logger_entry: "{" $@28 logger_params "}" #line 579 "agent_parser.yy" { ctx.stack_.pop_back(); @@ -1337,7 +1337,7 @@ namespace isc { namespace agent { #line 1338 "agent_parser.cc" break; - case 136: + case 136: // $@29: %empty #line 596 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); @@ -1345,7 +1345,7 @@ namespace isc { namespace agent { #line 1346 "agent_parser.cc" break; - case 137: + case 137: // name: "name" $@29 ":" "constant string" #line 598 "agent_parser.yy" { ElementPtr name(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); @@ -1355,7 +1355,7 @@ namespace isc { namespace agent { #line 1356 "agent_parser.cc" break; - case 138: + case 138: // debuglevel: "debuglevel" ":" "integer" #line 604 "agent_parser.yy" { ElementPtr dl(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location))); @@ -1364,7 +1364,7 @@ namespace isc { namespace agent { #line 1365 "agent_parser.cc" break; - case 139: + case 139: // $@30: %empty #line 609 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); @@ -1372,7 +1372,7 @@ namespace isc { namespace agent { #line 1373 "agent_parser.cc" break; - case 140: + case 140: // severity: "severity" $@30 ":" "constant string" #line 611 "agent_parser.yy" { ElementPtr sev(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); @@ -1382,7 +1382,7 @@ namespace isc { namespace agent { #line 1383 "agent_parser.cc" break; - case 141: + case 141: // $@31: %empty #line 617 "agent_parser.yy" { ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location))); @@ -1393,7 +1393,7 @@ namespace isc { namespace agent { #line 1394 "agent_parser.cc" break; - case 142: + case 142: // output_options_list: "output_options" $@31 ":" "[" output_options_list_content "]" #line 622 "agent_parser.yy" { ctx.stack_.pop_back(); @@ -1402,7 +1402,7 @@ namespace isc { namespace agent { #line 1403 "agent_parser.cc" break; - case 145: + case 145: // $@32: %empty #line 631 "agent_parser.yy" { ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location))); @@ -1412,7 +1412,7 @@ namespace isc { namespace agent { #line 1413 "agent_parser.cc" break; - case 146: + case 146: // output_entry: "{" $@32 output_params_list "}" #line 635 "agent_parser.yy" { ctx.stack_.pop_back(); @@ -1420,7 +1420,7 @@ namespace isc { namespace agent { #line 1421 "agent_parser.cc" break; - case 154: + case 154: // $@33: %empty #line 650 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); @@ -1428,7 +1428,7 @@ namespace isc { namespace agent { #line 1429 "agent_parser.cc" break; - case 155: + case 155: // output: "output" $@33 ":" "constant string" #line 652 "agent_parser.yy" { ElementPtr sev(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); @@ -1438,7 +1438,7 @@ namespace isc { namespace agent { #line 1439 "agent_parser.cc" break; - case 156: + case 156: // flush: "flush" ":" "boolean" #line 658 "agent_parser.yy" { ElementPtr flush(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location))); @@ -1447,7 +1447,7 @@ namespace isc { namespace agent { #line 1448 "agent_parser.cc" break; - case 157: + case 157: // maxsize: "maxsize" ":" "integer" #line 663 "agent_parser.yy" { ElementPtr maxsize(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location))); @@ -1456,7 +1456,7 @@ namespace isc { namespace agent { #line 1457 "agent_parser.cc" break; - case 158: + case 158: // maxver: "maxver" ":" "integer" #line 668 "agent_parser.yy" { ElementPtr maxver(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location))); @@ -1465,7 +1465,7 @@ namespace isc { namespace agent { #line 1466 "agent_parser.cc" break; - case 159: + case 159: // $@34: %empty #line 673 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); @@ -1473,7 +1473,7 @@ namespace isc { namespace agent { #line 1474 "agent_parser.cc" break; - case 160: + case 160: // pattern: "pattern" $@34 ":" "constant string" #line 675 "agent_parser.yy" { ElementPtr sev(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); @@ -1833,40 +1833,40 @@ namespace isc { namespace agent { } - const signed char AgentParser::yypact_ninf_ = -103; + const short AgentParser::yypact_ninf_ = -140; const signed char AgentParser::yytable_ninf_ = -1; const short AgentParser::yypact_[] = { - 56, -103, -103, -103, 8, 2, -5, 3, -103, -103, - -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, - -103, -103, -103, -103, 2, -14, 42, 1, -103, 44, - 51, 60, 62, 97, -103, 93, -103, -103, -103, 98, - -103, -103, -103, 99, -103, -103, -103, 101, -103, 57, - -103, -103, -103, -103, -103, -103, -103, -103, -103, -103, - -103, 2, 2, -103, 65, 104, -103, 109, 71, 111, - 114, 115, 113, 117, 118, 119, -103, 1, -103, -103, - -103, 120, 121, 85, -103, 87, 123, 89, -103, 127, - 128, 129, -103, 2, 1, -103, -103, -103, -103, -103, - 40, 130, 131, 132, -103, 59, -103, -103, -103, -103, - 63, -103, -103, -103, -103, -103, 134, 122, -103, -103, - 135, 133, -103, -103, 15, -103, -103, 138, 139, 140, - 40, -103, 11, -103, 130, 21, -103, 131, -11, 132, - -103, 141, 142, 143, -103, -103, -103, -103, -103, -103, - 80, -103, -103, -103, -103, -103, -103, -103, 81, -103, - -103, -103, -103, -103, -103, 147, -103, -103, -103, -103, - 82, -103, -103, -103, -103, -103, -103, 19, 19, 19, - 148, 149, 11, -103, 150, 151, 14, -103, 153, 154, - 92, 155, -11, -103, -103, -103, -103, -103, -103, 83, - -103, -103, -103, 84, 90, 103, 105, -103, 125, 2, - -103, 126, 157, -103, 136, -103, 159, 160, 19, -103, - -103, -103, -103, -103, -103, -103, -103, 158, -103, 137, - 124, -103, -103, 26, -103, -103, -103, -103, 43, 158, - -103, -103, 165, 168, 169, -103, 91, -103, -103, -103, - -103, -103, -103, -103, 170, 144, 145, 152, 171, 43, - -103, 156, -103, -103, -103, 161, -103, -103, -103 + 75, -140, -140, -140, 4, 2, 1, 3, -140, -140, + -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, + -140, -140, -140, -140, 2, -36, 39, 6, -140, 56, + 9, 59, 62, 61, -140, 63, -140, -140, -140, 98, + -140, -140, -140, 100, -140, -140, -140, 105, -140, 28, + -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, + -140, 2, 2, -140, 50, 106, -140, 113, 80, 114, + 115, 116, 92, 117, 118, 120, -140, 6, -140, -140, + -140, 121, 122, 89, -140, 90, 123, 91, -140, 129, + 130, 131, -140, 2, 6, -140, -140, -140, -140, -140, + 41, 132, 133, 134, -140, 58, -140, -140, -140, -140, + 76, -140, -140, -140, -140, -140, 136, 124, -140, -140, + 137, 125, -140, -140, 94, -140, -140, 140, 141, 142, + 41, -140, -1, -140, 132, -12, -140, 133, 23, 134, + -140, 143, 144, 145, -140, -140, -140, -140, -140, -140, + 77, -140, -140, -140, -140, -140, -140, -140, 78, -140, + -140, -140, -140, -140, -140, 149, -140, -140, -140, -140, + 79, -140, -140, -140, -140, -140, -140, 13, 13, 13, + 150, 154, -1, -140, 155, 156, -2, -140, 157, 158, + 104, 159, 23, -140, -140, -140, -140, -140, -140, 85, + -140, -140, -140, 86, 87, 96, 107, -140, 126, 123, + -140, 127, 165, -140, 135, -140, 160, 167, 13, -140, + -140, -140, -140, -140, -140, -140, -140, 166, -140, 138, + 152, -140, -140, 95, -140, -140, -140, -140, 40, 166, + -140, -140, 168, 171, 172, -140, 88, -140, -140, -140, + -140, -140, -140, -140, 174, 103, 139, 146, 175, 40, + -140, 148, -140, -140, -140, 151, -140, -140, -140 }; const unsigned char @@ -1901,20 +1901,20 @@ namespace isc { namespace agent { 146, 0, 156, 157, 158, 0, 148, 155, 160 }; - const signed char + const short AgentParser::yypgoto_[] = { - -103, -103, -103, -103, -103, -103, -103, -103, -24, 94, - -103, -103, -103, -103, -103, -103, -103, -103, -26, -103, - -103, -103, -103, -103, -103, 32, 100, -103, -103, -103, - -103, -103, -22, -103, -21, -103, -103, -103, -103, -103, - 39, -103, -103, -4, -103, -103, -103, -103, -103, -103, - -103, 53, -103, -103, -103, -103, -103, -103, -102, -37, - -103, -103, -103, -103, -103, -103, -103, -103, -103, 50, - -103, -103, 4, -103, -103, -103, -103, -103, -103, -103, - 48, -103, -103, -2, -103, -103, -103, -103, -103, -103, - -103, -103, -48, -103, -103, -67, -103, -103, -103, -103, - -103, -103, -103 + -140, -140, -140, -140, -140, -140, -140, -140, -19, -83, + -140, -72, -140, -140, -140, -140, -140, -140, -27, -140, + -140, -140, -140, -140, -140, 93, 108, -140, -140, -140, + -140, -140, -26, -140, -25, -140, -140, -140, -140, -140, + 44, -140, -140, -3, -140, -140, -140, -140, -140, -140, + -140, 54, -140, -140, -140, -140, -140, -140, -139, -32, + -140, -140, -140, -140, -140, -140, -140, -140, -140, 57, + -140, -140, 10, -140, -140, -140, -140, -140, -140, -140, + 49, -140, -140, 5, -140, -140, -140, -140, -140, -140, + -140, -140, -45, -140, -140, -64, -140, -140, -140, -140, + -140, -140, -140 }; const short @@ -1936,53 +1936,51 @@ namespace isc { namespace agent { const short AgentParser::yytable_[] = { - 28, 48, 20, 41, 42, 54, 55, 9, 8, 10, - 22, 11, 38, 39, 40, 41, 42, 43, 139, 163, - 164, 140, 165, 166, 44, 41, 42, 45, 31, 239, - 46, 47, 240, 41, 42, 145, 146, 79, 80, 194, - 195, 155, 156, 47, 12, 13, 14, 15, 155, 156, - 60, 48, 34, 47, 61, 54, 55, 106, 107, 108, - 77, 47, 77, 47, 62, 78, 130, 126, 48, 104, - 63, 131, 54, 55, 109, 241, 203, 204, 242, 243, - 244, 245, 47, 182, 186, 192, 218, 218, 183, 187, - 193, 219, 220, 218, 259, 1, 2, 3, 221, 260, - 64, 66, 68, 72, 109, 76, 147, 81, 82, 157, - 148, 149, 167, 83, 84, 85, 168, 169, 86, 87, - 88, 89, 90, 91, 93, 134, 105, 95, 94, 96, - 10, 99, 101, 102, 103, 213, 137, 115, 119, 123, - 133, 136, 141, 142, 143, 222, 236, 223, 177, 178, - 179, 190, 205, 206, 208, 209, 147, 211, 212, 214, - 148, 149, 227, 229, 230, 232, 167, 224, 226, 255, - 168, 169, 256, 257, 261, 265, 162, 92, 228, 235, - 97, 231, 210, 144, 154, 225, 207, 176, 263, 262, - 215, 253, 266, 0, 0, 264, 0, 0, 267, 0, - 0, 0, 0, 268 + 48, 54, 55, 97, 8, 28, 31, 9, 20, 10, + 22, 11, 61, 41, 42, 155, 156, 38, 39, 40, + 41, 42, 43, 145, 146, 155, 156, 41, 42, 44, + 47, 77, 45, 194, 195, 46, 78, 41, 42, 203, + 204, 47, 79, 80, 12, 13, 14, 15, 47, 34, + 48, 54, 55, 163, 164, 47, 165, 166, 106, 107, + 108, 77, 60, 62, 64, 47, 126, 48, 54, 55, + 63, 66, 241, 109, 104, 242, 243, 244, 245, 130, + 182, 186, 192, 47, 131, 183, 187, 193, 218, 218, + 218, 259, 81, 219, 220, 221, 260, 139, 239, 88, + 140, 240, 68, 109, 72, 147, 148, 149, 157, 76, + 82, 167, 168, 169, 1, 2, 3, 83, 85, 86, + 87, 89, 90, 84, 91, 93, 97, 134, 137, 94, + 10, 95, 96, 99, 101, 102, 103, 225, 222, 115, + 119, 123, 133, 136, 141, 142, 143, 213, 262, 223, + 177, 178, 179, 190, 205, 147, 148, 149, 206, 208, + 209, 211, 212, 214, 229, 167, 168, 169, 224, 226, + 227, 230, 255, 232, 236, 256, 257, 228, 261, 265, + 235, 162, 263, 210, 144, 92, 231, 105, 176, 264, + 267, 154, 207, 268, 253, 266, 0, 215 }; const short AgentParser::yycheck_[] = { - 24, 27, 7, 14, 15, 27, 27, 5, 0, 7, - 7, 9, 11, 12, 13, 14, 15, 16, 3, 30, - 31, 6, 33, 34, 23, 14, 15, 26, 42, 3, - 29, 42, 6, 14, 15, 24, 25, 61, 62, 20, - 21, 27, 28, 42, 42, 43, 44, 45, 27, 28, - 6, 77, 10, 42, 3, 77, 77, 17, 18, 19, - 3, 42, 3, 42, 4, 8, 3, 8, 94, 93, - 8, 8, 94, 94, 100, 32, 178, 179, 35, 36, - 37, 38, 42, 3, 3, 3, 3, 3, 8, 8, - 8, 8, 8, 3, 3, 39, 40, 41, 8, 8, - 3, 8, 4, 4, 130, 4, 132, 42, 4, 135, - 132, 132, 138, 4, 43, 4, 138, 138, 4, 4, - 7, 4, 4, 4, 4, 3, 94, 42, 7, 42, - 7, 42, 5, 5, 5, 43, 3, 7, 7, 7, - 6, 6, 4, 4, 4, 42, 22, 42, 7, 7, - 7, 4, 4, 4, 4, 4, 182, 4, 4, 4, - 182, 182, 5, 4, 4, 7, 192, 42, 42, 4, - 192, 192, 4, 4, 4, 4, 137, 77, 42, 42, - 86, 218, 186, 130, 134, 209, 182, 139, 43, 45, - 192, 239, 259, -1, -1, 43, -1, -1, 42, -1, - -1, -1, -1, 42 + 27, 27, 27, 86, 0, 24, 42, 5, 7, 7, + 7, 9, 3, 14, 15, 27, 28, 11, 12, 13, + 14, 15, 16, 24, 25, 27, 28, 14, 15, 23, + 42, 3, 26, 20, 21, 29, 8, 14, 15, 178, + 179, 42, 61, 62, 42, 43, 44, 45, 42, 10, + 77, 77, 77, 30, 31, 42, 33, 34, 17, 18, + 19, 3, 6, 4, 3, 42, 8, 94, 94, 94, + 8, 8, 32, 100, 93, 35, 36, 37, 38, 3, + 3, 3, 3, 42, 8, 8, 8, 8, 3, 3, + 3, 3, 42, 8, 8, 8, 8, 3, 3, 7, + 6, 6, 4, 130, 4, 132, 132, 132, 135, 4, + 4, 138, 138, 138, 39, 40, 41, 4, 4, 4, + 4, 4, 4, 43, 4, 4, 209, 3, 3, 7, + 7, 42, 42, 42, 5, 5, 5, 209, 42, 7, + 7, 7, 6, 6, 4, 4, 4, 43, 45, 42, + 7, 7, 7, 4, 4, 182, 182, 182, 4, 4, + 4, 4, 4, 4, 4, 192, 192, 192, 42, 42, + 5, 4, 4, 7, 22, 4, 4, 42, 4, 4, + 42, 137, 43, 186, 130, 77, 218, 94, 139, 43, + 42, 134, 182, 42, 239, 259, -1, 192 }; const unsigned char @@ -2010,7 +2008,7 @@ namespace isc { namespace agent { 4, 134, 3, 8, 20, 21, 64, 78, 80, 104, 105, 106, 108, 104, 104, 4, 4, 118, 4, 4, 89, 4, 4, 43, 4, 129, 107, 109, 3, 8, - 8, 8, 42, 42, 42, 54, 42, 5, 42, 4, + 8, 8, 42, 42, 42, 57, 42, 5, 42, 4, 4, 105, 7, 137, 138, 42, 22, 110, 139, 3, 6, 32, 35, 36, 37, 38, 140, 141, 142, 144, 145, 146, 147, 138, 143, 4, 4, 4, 148, 3, @@ -2158,7 +2156,7 @@ namespace isc { namespace agent { #line 14 "agent_parser.yy" } } // isc::agent -#line 2162 "agent_parser.cc" +#line 2160 "agent_parser.cc" #line 681 "agent_parser.yy" diff --git a/src/bin/agent/agent_parser.h b/src/bin/agent/agent_parser.h index 45be92fb45..0668130a64 100644 --- a/src/bin/agent/agent_parser.h +++ b/src/bin/agent/agent_parser.h @@ -1,4 +1,4 @@ -// A Bison parser, made by GNU Bison 3.6.4. +// A Bison parser, made by GNU Bison 3.7.2. // Skeleton interface for Bison LALR(1) parsers in C++ @@ -726,25 +726,25 @@ namespace isc { namespace agent { { switch (this->kind ()) { - case 54: // value - case 57: // map_value - case 110: // socket_type_value + case symbol_kind::S_value: // value + case symbol_kind::S_map_value: // map_value + case symbol_kind::S_socket_type_value: // socket_type_value value.move< ElementPtr > (std::move (that.value)); break; - case 45: // "boolean" + case symbol_kind::S_BOOLEAN: // "boolean" value.move< bool > (std::move (that.value)); break; - case 44: // "floating point" + case symbol_kind::S_FLOAT: // "floating point" value.move< double > (std::move (that.value)); break; - case 43: // "integer" + case symbol_kind::S_INTEGER: // "integer" value.move< int64_t > (std::move (that.value)); break; - case 42: // "constant string" + case symbol_kind::S_STRING: // "constant string" value.move< std::string > (std::move (that.value)); break; @@ -858,25 +858,25 @@ namespace isc { namespace agent { // Value type destructor. switch (yykind) { - case 54: // value - case 57: // map_value - case 110: // socket_type_value + case symbol_kind::S_value: // value + case symbol_kind::S_map_value: // map_value + case symbol_kind::S_socket_type_value: // socket_type_value value.template destroy< ElementPtr > (); break; - case 45: // "boolean" + case symbol_kind::S_BOOLEAN: // "boolean" value.template destroy< bool > (); break; - case 44: // "floating point" + case symbol_kind::S_FLOAT: // "floating point" value.template destroy< double > (); break; - case 43: // "integer" + case symbol_kind::S_INTEGER: // "integer" value.template destroy< int64_t > (); break; - case 42: // "constant string" + case symbol_kind::S_STRING: // "constant string" value.template destroy< std::string > (); break; @@ -1821,7 +1821,7 @@ switch (yykind) /// \param yyvalue the value to check static bool yy_table_value_is_error_ (int yyvalue); - static const signed char yypact_ninf_; + static const short yypact_ninf_; static const signed char yytable_ninf_; /// Convert a scanner token kind \a t to a symbol kind. @@ -1847,7 +1847,7 @@ switch (yykind) static const unsigned char yydefact_[]; // YYPGOTO[NTERM-NUM]. - static const signed char yypgoto_[]; + static const short yypgoto_[]; // YYDEFGOTO[NTERM-NUM]. static const short yydefgoto_[]; @@ -1920,7 +1920,7 @@ switch (yykind) void move (by_state& that); /// The symbol kind (corresponding to \a state). - /// \a S_YYEMPTY when empty. + /// \a symbol_kind::S_YYEMPTY when empty. symbol_kind_type kind () const YY_NOEXCEPT; /// The state number used to denote an empty symbol. @@ -2099,7 +2099,7 @@ switch (yykind) /// Constants. enum { - yylast_ = 203, ///< Last index in yytable_. + yylast_ = 197, ///< Last index in yytable_. yynnts_ = 103, ///< Number of nonterminal symbols. yyfinal_ = 8 ///< Termination state number. }; @@ -2152,11 +2152,12 @@ switch (yykind) 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45 }; - const int user_token_number_max_ = 300; + // Last valid token kind. + const int code_max = 300; if (t <= 0) return symbol_kind::S_YYEOF; - else if (t <= user_token_number_max_) + else if (t <= code_max) return YY_CAST (symbol_kind_type, translate_table[t]); else return symbol_kind::S_YYUNDEF; @@ -2171,25 +2172,25 @@ switch (yykind) { switch (this->kind ()) { - case 54: // value - case 57: // map_value - case 110: // socket_type_value + case symbol_kind::S_value: // value + case symbol_kind::S_map_value: // map_value + case symbol_kind::S_socket_type_value: // socket_type_value value.copy< ElementPtr > (YY_MOVE (that.value)); break; - case 45: // "boolean" + case symbol_kind::S_BOOLEAN: // "boolean" value.copy< bool > (YY_MOVE (that.value)); break; - case 44: // "floating point" + case symbol_kind::S_FLOAT: // "floating point" value.copy< double > (YY_MOVE (that.value)); break; - case 43: // "integer" + case symbol_kind::S_INTEGER: // "integer" value.copy< int64_t > (YY_MOVE (that.value)); break; - case 42: // "constant string" + case symbol_kind::S_STRING: // "constant string" value.copy< std::string > (YY_MOVE (that.value)); break; @@ -2222,25 +2223,25 @@ switch (yykind) super_type::move (s); switch (this->kind ()) { - case 54: // value - case 57: // map_value - case 110: // socket_type_value + case symbol_kind::S_value: // value + case symbol_kind::S_map_value: // map_value + case symbol_kind::S_socket_type_value: // socket_type_value value.move< ElementPtr > (YY_MOVE (s.value)); break; - case 45: // "boolean" + case symbol_kind::S_BOOLEAN: // "boolean" value.move< bool > (YY_MOVE (s.value)); break; - case 44: // "floating point" + case symbol_kind::S_FLOAT: // "floating point" value.move< double > (YY_MOVE (s.value)); break; - case 43: // "integer" + case symbol_kind::S_INTEGER: // "integer" value.move< int64_t > (YY_MOVE (s.value)); break; - case 42: // "constant string" + case symbol_kind::S_STRING: // "constant string" value.move< std::string > (YY_MOVE (s.value)); break; @@ -2307,8 +2308,7 @@ switch (yykind) #line 14 "agent_parser.yy" } } // isc::agent -#line 2311 "agent_parser.h" - +#line 2312 "agent_parser.h" diff --git a/src/bin/agent/location.hh b/src/bin/agent/location.hh index 1c93a118bf..c440be17db 100644 --- a/src/bin/agent/location.hh +++ b/src/bin/agent/location.hh @@ -1,5 +1,5 @@ -// Generated 202009021532 -// A Bison parser, made by GNU Bison 3.7.1. +// Generated 202009120852 +// A Bison parser, made by GNU Bison 3.7.2. // Locations for Bison parsers in C++ diff --git a/src/bin/agent/position.hh b/src/bin/agent/position.hh index 0403c938c4..fb813a89c6 100644 --- a/src/bin/agent/position.hh +++ b/src/bin/agent/position.hh @@ -1,5 +1,5 @@ -// Generated 202009021532 -// A Bison parser, made by GNU Bison 3.7.1. +// Generated 202009120852 +// A Bison parser, made by GNU Bison 3.7.2. // Starting with Bison 3.2, this file is useless: the structure it // used to define is now defined in "location.hh". diff --git a/src/bin/agent/stack.hh b/src/bin/agent/stack.hh index e6bfe5d25d..ddc4320848 100644 --- a/src/bin/agent/stack.hh +++ b/src/bin/agent/stack.hh @@ -1,5 +1,5 @@ -// Generated 202009021532 -// A Bison parser, made by GNU Bison 3.7.1. +// Generated 202009120852 +// A Bison parser, made by GNU Bison 3.7.2. // Starting with Bison 3.2, this file is useless: the structure it // used to define is now defined with the parser itself. -- GitLab From b13915dea4760843604124ff3bda8582d29f14a1 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Sat, 12 Sep 2020 17:36:44 +0200 Subject: [PATCH 21/33] [#1304] Addressed comments (but not for syntax) --- doc/sphinx/arm/agent.rst | 2 +- doc/sphinx/arm/hooks-ha.rst | 4 ++-- doc/sphinx/arm/shell.rst | 7 ++++++- src/lib/http/basic_auth_config.h | 10 +++++++--- 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/doc/sphinx/arm/agent.rst b/doc/sphinx/arm/agent.rst index d2f26693a0..a65d2edaa3 100644 --- a/doc/sphinx/arm/agent.rst +++ b/doc/sphinx/arm/agent.rst @@ -137,7 +137,7 @@ ability to store comments or descriptions; the parser translates a "comment" entry into a user context with the entry, which allows a comment to be attached within the configuration itself. -The basic HTTP authentication was added by Kea 1.7.10. It protects +The basic HTTP authentication was added by Kea 1.9.0. It protects against not authorized uses of the control agent by local users. For the protection against remote attackers HTTPS and reverse proxy of :ref:`agent-secure-connection` provide a stronger security. diff --git a/doc/sphinx/arm/hooks-ha.rst b/doc/sphinx/arm/hooks-ha.rst index a679cabaeb..13967b8550 100644 --- a/doc/sphinx/arm/hooks-ha.rst +++ b/doc/sphinx/arm/hooks-ha.rst @@ -581,7 +581,7 @@ server. It may also contain an unlimited number of backup servers. In this example, there is one backup server which receives lease updates from the active servers. -Since Kea version 1.7.10 the basic HTTP authentication is available +Since Kea version 1.9.0 the basic HTTP authentication is available to protect the Kea control agent against local attackers. These are the parameters specified for each of the peers within this @@ -1291,7 +1291,7 @@ load-balancing and the hot-standby cases presented in previous sections. } } -Since Kea version 1.7.10 the basic HTTP authentication is supported. +Since Kea version 1.9.0 the basic HTTP authentication is supported. .. _ha-maintenance: diff --git a/doc/sphinx/arm/shell.rst b/doc/sphinx/arm/shell.rst index 9380a316aa..39675c048d 100644 --- a/doc/sphinx/arm/shell.rst +++ b/doc/sphinx/arm/shell.rst @@ -22,7 +22,7 @@ As the primary purpose of the Kea shell is as a tool in a scripting environment, it is not interactive. However, following simple guidelines it can be run manually. -Kea 1.7.10 introduced basic HTTP authentication support. +Kea 1.9.0 introduced basic HTTP authentication support. Shell Usage =========== @@ -127,3 +127,8 @@ people interested in integrating their management environments with Kea) than as a serious management client. It is not likely to be significantly expanded in the future; it is, and will remain, a simple tool. + +.. note:: + + When using this tool with basic HTTP authentication please not forget + that command line arguments are not hidden to local users. diff --git a/src/lib/http/basic_auth_config.h b/src/lib/http/basic_auth_config.h index a5d3e74a6c..c459ba3c57 100644 --- a/src/lib/http/basic_auth_config.h +++ b/src/lib/http/basic_auth_config.h @@ -18,7 +18,11 @@ namespace isc { namespace http { -/// @brief Type of basic HTTP authentication credential and user id map. +/// @brief Type of basic HTTP authentication credential and user id map, +/// e.g. map["am9obmRvZTpzZWNyZXQx" = "johndoe". +/// +/// The map is used to verify a received credential: if it is not in it +/// the authentication fails, if it is in it the user id is logged. typedef std::unordered_map BasicHttpAuthMap; /// @brief Basic HTTP authentication client configuration. @@ -52,10 +56,10 @@ public: private: - /// @brief The user id. + /// @brief The user id e.g. johndoe. std::string user_; - /// @brief The password. + /// @brief The password e.g. secret1. std::string password_; }; -- GitLab From 5b4ed2764e0f940578b8d4c31c19b746d6d2d928 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Sat, 12 Sep 2020 18:14:44 +0200 Subject: [PATCH 22/33] [#1304] Checkpoint before regen --- src/bin/agent/agent_lexer.ll | 103 ++++++++++++++++++----------- src/bin/agent/agent_parser.yy | 111 +++++++++++++++++++++----------- src/bin/agent/parser_context.cc | 8 ++- src/bin/agent/parser_context.h | 15 +++-- 4 files changed, 155 insertions(+), 82 deletions(-) diff --git a/src/bin/agent/agent_lexer.ll b/src/bin/agent/agent_lexer.ll index 70805ec4b7..962abf0c1c 100644 --- a/src/bin/agent/agent_lexer.ll +++ b/src/bin/agent/agent_lexer.ll @@ -200,21 +200,12 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence} } } -\"basic-authentication-realm\" { - switch(driver.ctx_) { - case ParserContext::AGENT: - return AgentParser::make_BASIC_AUTHENTICATION_REALM(driver.loc_); - default: - return AgentParser::make_STRING("basic-authentication-realm", driver.loc_); - } -} - \"user-context\" { switch(driver.ctx_) { case ParserContext::AGENT: case ParserContext::SERVER: case ParserContext::LOGGERS: - case ParserContext::BASIC_AUTHENTICATIONS: + case ParserContext::CLIENTS: return AgentParser::make_USER_CONTEXT(driver.loc_); default: return AgentParser::make_STRING("user-context", driver.loc_); @@ -226,13 +217,76 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence} case ParserContext::AGENT: case ParserContext::SERVER: case ParserContext::LOGGERS: - case ParserContext::BASIC_AUTHENTICATIONS: + case ParserContext::CLIENTS: return AgentParser::make_COMMENT(driver.loc_); default: return AgentParser::make_STRING("comment", driver.loc_); } } +\"authentication\" { + switch(driver.ctx_) { + case ParserContext::AGENT: + return AgentParser::make_AUTHENTICATION(driver.loc_); + default: + return AgentParser::make_STRING("authentication", driver.loc_); + } +} + +\"type\" { + switch(driver.ctx_) { + case ParserContext::AUTHENTICATION: + return AgentParser::make_TYPE(driver.loc_); + default: + return AgentParser::make_STRING("type", driver.loc_); + } +} + +\"basic\" { + switch(driver.ctx_) { + case ParserContext::AUTH_TYPE: + return AgentParser::make_BASIC(driver.loc_); + default: + return AgentParser::make_STRING("basic", driver.loc_); + } +} + +\"realm\" { + switch(driver.ctx_) { + case ParserContext::AUTHENTICATION: + return AgentParser::make_REALM(driver.loc_); + default: + return AgentParser::make_STRING("authentication", driver.loc_); + } +} + +\"clients\" { + switch(driver.ctx_) { + case ParserContext::AUTHENTICATION: + return AgentParser::make_CLIENTS(driver.loc_); + default: + return AgentParser::make_STRING("clients", driver.loc_); + } +} + +\"user\" { + switch(driver.ctx_) { + case ParserContext::CLIENTS: + return AgentParser::make_USER(driver.loc_); + default: + return AgentParser::make_STRING("user", driver.loc_); + } +} + +\"password\" { + switch(driver.ctx_) { + case ParserContext::CLIENTS: + return AgentParser::make_PASSWORD(driver.loc_); + default: + return AgentParser::make_STRING("password", driver.loc_); + } +} + \"control-sockets\" { switch(driver.ctx_) { case ParserContext::AGENT: @@ -413,33 +467,6 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence} } } -\"basic-authentications\" { - switch(driver.ctx_) { - case ParserContext::AGENT: - return AgentParser::make_BASIC_AUTHENTICATIONS(driver.loc_); - default: - return AgentParser::make_STRING("basic-authentications", driver.loc_); - } -} - -\"user\" { - switch(driver.ctx_) { - case ParserContext::BASIC_AUTHENTICATIONS: - return AgentParser::make_USER(driver.loc_); - default: - return AgentParser::make_STRING("user", driver.loc_); - } -} - -\"password\" { - switch(driver.ctx_) { - case ParserContext::BASIC_AUTHENTICATIONS: - return AgentParser::make_PASSWORD(driver.loc_); - default: - return AgentParser::make_STRING("password", driver.loc_); - } -} - {JSONString} { /* A string has been matched. It contains the actual string and single quotes. We need to get those quotes out of the way and just use its content, e.g. diff --git a/src/bin/agent/agent_parser.yy b/src/bin/agent/agent_parser.yy index 84c435dd55..5f8c981b81 100644 --- a/src/bin/agent/agent_parser.yy +++ b/src/bin/agent/agent_parser.yy @@ -51,11 +51,18 @@ using namespace std; CONTROL_AGENT "Control-agent" HTTP_HOST "http-host" HTTP_PORT "http-port" - BASIC_AUTHENTICATION_REALM "basic-authentication-realm" USER_CONTEXT "user-context" COMMENT "comment" + AUTHENTICATION "authentication" + TYPE "type" + BASIC "basic" + REALM "realm" + CLIENTS "clients" + USER "user" + PASSWORD "password" + CONTROL_SOCKETS "control-sockets" DHCP4_SERVER "dhcp4" DHCP6_SERVER "dhcp6" @@ -64,10 +71,6 @@ using namespace std; SOCKET_TYPE "socket-type" UNIX "unix" - BASIC_AUTHENTICATIONS "basic-authentications" - USER "user" - PASSWORD "password" - HOOKS_LIBRARIES "hooks-libraries" LIBRARY "library" PARAMETERS "parameters" @@ -265,9 +268,8 @@ global_params: global_param // Dhcp6. global_param: http_host | http_port - | basic_authentication_realm + | authentication | control_sockets - | basic_authentications | hooks_libraries | loggers | user_context @@ -288,14 +290,6 @@ http_port: HTTP_PORT COLON INTEGER { ctx.stack_.back()->set("http-port", prf); }; -basic_authentication_realm: BASIC_AUTHENTICATION_REALM { - ctx.enter(ctx.NO_KEYWORDS); -} COLON STRING { - ElementPtr realm(new StringElement($4, ctx.loc2pos(@4))); - ctx.stack_.back()->set("basic-authentication-realm", realm); - ctx.leave(); -}; - user_context: USER_CONTEXT { ctx.enter(ctx.NO_KEYWORDS); } COLON map_value { @@ -496,44 +490,87 @@ socket_type_value : UNIX { $$ = ElementPtr(new StringElement("unix", ctx.loc2pos // --- control-sockets end here ------------------------------------------------ -// --- basic-authentications starts here ----------------------------------------------------- +// --- authentication starts here ----------------------------------------------------- + +authentication: AUTHENTICATION { + // Add unique here + ElementPtr m(new MapElement(ctx.loc2pos(@1))); + ctx.stack_.back()->set("authentication", m); + ctx.stack_.push_back(m); + ctx.enter(ctx.AUTHENTICATION); +} COLON LCURLY_BRACKET auth_params RCURLY_BRACKET { + // The type parameter is required + ctx.require("type", ctx.loc2pos(@4), ctx.loc2pos(@6)); + ctx.stack_.pop_back(); + ctx.leave(); +}; -basic_authentications: BASIC_AUTHENTICATIONS { +auth_params: auth_param + | auth_params COMMA auth_param + ; + +auth_param: type + | realm + | clients + ; + +type: TYPE { + // Add unique here + ctx.enter(ctx.AUTH_TYPE); +} COLON auth_type { + ctx.stack_.back()->set("type", $4); + ctx.leave(); +}; + +auth_type: BASIC { $$ = ElementPtr(new StringElement("basic", ctx.loc2pos(@1))); } + ; + +realm: REALM { + // Add unique here + ctx.enter(ctx.NO_KEYWORD); +} COLON STRING { + ElementPtr realm(new StringElement($4, ctx.loc2pos(@4))); + ctx.stack_.back()->set("realm", realm); + ctx.leave(); +}; + +clients: CLIENTS { + // Add unique here ElementPtr l(new ListElement(ctx.loc2pos(@1))); - ctx.stack_.back()->set("basic-authentications", l); + ctx.stack_.back()->set("clients", l); ctx.stack_.push_back(l); - ctx.enter(ctx.BASIC_AUTHENTICATIONS); -} COLON LSQUARE_BRACKET basic_auth_list RSQUARE_BRACKET { + ctx.enter(ctx.CLIENTS); +} COLON LSQUARE_BRACKET clients_list RSQUARE_BRACKET { ctx.stack_.pop_back(); ctx.leave(); }; -basic_auth_list: %empty - | not_empty_basic_auth_list - ; +clients_list: %empty + | not_empty_clients_list + ; -not_empty_basic_auth_list: basic_auth - | not_empty_basic_auth_list COMMA basic_auth - ; +not_empty_clients_list: basic_auth + | not_empty_clients_list COMMA basic_auth + ; basic_auth: LCURLY_BRACKET { ElementPtr m(new MapElement(ctx.loc2pos(@1))); ctx.stack_.back()->add(m); ctx.stack_.push_back(m); -} basic_auth_params RCURLY_BRACKET { +} clients_params RCURLY_BRACKET { ctx.stack_.pop_back(); }; -basic_auth_params: basic_auth_param - | basic_auth_params COMMA basic_auth_param - ; +clients_params: clients_param + | clients_params COMMA clients_param + ; -basic_auth_param: user - | password - | user_context - | comment - | unknown_map_entry - ; +clients_param: user + | password + | user_context + | comment + | unknown_map_entry + ; user: USER { ctx.enter(ctx.NO_KEYWORDS); @@ -551,7 +588,7 @@ password: PASSWORD { ctx.leave(); }; -// --- basic-authentications end here ----------------------------------------------------- +// --- authentication end here ----------------------------------------------------- // --- Loggers starts here ----------------------------------------------------- diff --git a/src/bin/agent/parser_context.cc b/src/bin/agent/parser_context.cc index 3517252645..c0a1a4aa5e 100644 --- a/src/bin/agent/parser_context.cc +++ b/src/bin/agent/parser_context.cc @@ -123,6 +123,12 @@ ParserContext::contextName() return ("toplevel"); case AGENT: return ("Control-agent"); + case AUTHENTICATION: + return ("authentication"); + case AUTH_TYPE: + return ("auth-type"); + case CLIENTS: + return ("clients"); case CONTROL_SOCKETS: return ("control-sockets"); case SERVER: @@ -135,8 +141,6 @@ ParserContext::contextName() return ("loggers"); case OUTPUT_OPTIONS: return ("output-options"); - case BASIC_AUTHENTICATIONS: - return ("basic-authentications"); default: return ("__unknown__"); } diff --git a/src/bin/agent/parser_context.h b/src/bin/agent/parser_context.h index 32572f669a..ffcd8e3530 100644 --- a/src/bin/agent/parser_context.h +++ b/src/bin/agent/parser_context.h @@ -158,6 +158,15 @@ public: ///< Used while parsing content of Agent. AGENT, + ///< Used while parsing Control-agent/Authentication. + AUTHENTICATION, + + ///< Used while parsing Control-agent/Authentication/type. + AUTH_TYPE, + + ///< Used while parsing Control-agent/Authentication/clients. + CLIENTS, + ///< Used while parsing Control-agent/control-sockets. CONTROL_SOCKETS, @@ -174,11 +183,7 @@ public: LOGGERS, ///< Used while parsing Control-agent/loggers/output_options structures. - OUTPUT_OPTIONS, - - ///< Used while parsing Control-agent/basic-authentications. - BASIC_AUTHENTICATIONS - + OUTPUT_OPTIONS } LexerContext; /// @brief File name -- GitLab From 357d67cd411cab5a77f06f22dcf72d2d286a16ee Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Sat, 12 Sep 2020 18:17:19 +0200 Subject: [PATCH 23/33] [#1304] Checkpoint before regen (2) --- src/bin/agent/agent_parser.yy | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/bin/agent/agent_parser.yy b/src/bin/agent/agent_parser.yy index 5f8c981b81..36c686288b 100644 --- a/src/bin/agent/agent_parser.yy +++ b/src/bin/agent/agent_parser.yy @@ -103,6 +103,7 @@ using namespace std; %type value %type map_value %type socket_type_value +%type auth_type_value %printer { yyoutput << $$; } <*>; @@ -509,20 +510,20 @@ auth_params: auth_param | auth_params COMMA auth_param ; -auth_param: type +auth_param: auth_type | realm | clients ; -type: TYPE { +auth_type: TYPE { // Add unique here ctx.enter(ctx.AUTH_TYPE); -} COLON auth_type { +} COLON auth_type_value { ctx.stack_.back()->set("type", $4); ctx.leave(); }; -auth_type: BASIC { $$ = ElementPtr(new StringElement("basic", ctx.loc2pos(@1))); } +auth_type_value: BASIC { $$ = ElementPtr(new StringElement("basic", ctx.loc2pos(@1))); } ; realm: REALM { -- GitLab From 940599e958d258b4908fede2622b2ba45472383f Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Sat, 12 Sep 2020 16:17:16 +0000 Subject: [PATCH 24/33] [#1304] regen files --- src/bin/agent/agent_lexer.cc | 1530 +++++++++++++++++---------------- src/bin/agent/agent_parser.cc | 1027 ++++++++++++---------- src/bin/agent/agent_parser.h | 521 ++++++----- src/bin/agent/location.hh | 2 +- src/bin/agent/position.hh | 2 +- src/bin/agent/stack.hh | 2 +- 6 files changed, 1635 insertions(+), 1449 deletions(-) diff --git a/src/bin/agent/agent_lexer.cc b/src/bin/agent/agent_lexer.cc index d052cc765c..07d4b7ddce 100644 --- a/src/bin/agent/agent_lexer.cc +++ b/src/bin/agent/agent_lexer.cc @@ -691,8 +691,8 @@ static void yynoreturn yy_fatal_error ( const char* msg ); /* %% [3.0] code to copy yytext_ptr to yytext[] goes here, if %array \ */\ (yy_c_buf_p) = yy_cp; /* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */ -#define YY_NUM_RULES 59 -#define YY_END_OF_BUFFER 60 +#define YY_NUM_RULES 62 +#define YY_END_OF_BUFFER 63 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -700,45 +700,46 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static const flex_int16_t yy_accept[342] = +static const flex_int16_t yy_accept[352] = { 0, - 52, 52, 0, 0, 0, 0, 0, 0, 0, 0, - 60, 58, 10, 11, 58, 1, 52, 49, 52, 52, - 58, 51, 50, 58, 58, 58, 58, 58, 45, 46, - 58, 58, 58, 47, 48, 5, 5, 5, 58, 58, - 58, 10, 11, 0, 0, 41, 0, 0, 0, 0, + 55, 55, 0, 0, 0, 0, 0, 0, 0, 0, + 63, 61, 10, 11, 61, 1, 55, 52, 55, 55, + 61, 54, 53, 61, 61, 61, 61, 61, 48, 49, + 61, 61, 61, 50, 51, 5, 5, 5, 61, 61, + 61, 10, 11, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 52, 52, 0, 51, 52, 3, 2, 6, 0, - 52, 0, 0, 0, 0, 0, 0, 4, 0, 0, - 9, 0, 42, 0, 0, 0, 44, 0, 0, 0, + 0, 0, 0, 1, 55, 55, 0, 54, 55, 3, + 2, 6, 0, 55, 0, 0, 0, 0, 0, 0, + 4, 0, 0, 9, 0, 45, 0, 0, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, - 0, 0, 0, 0, 8, 0, 0, 0, 43, 0, - 0, 0, 0, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 57, 55, 0, 54, 53, 0, 0, 0, + 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, + 0, 8, 0, 0, 0, 46, 0, 0, 0, 0, + 0, 0, 27, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 60, 58, 0, 57, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 56, 53, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 29, 0, 0, 0, 0, 0, 0, 24, 39, - - 0, 0, 0, 0, 0, 0, 0, 0, 19, 20, - 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 7, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 34, 31, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, - 0, 0, 0, 0, 26, 28, 33, 0, 0, 0, - 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 40, 37, 0, 0, 0, 0, - 0, 0, 0, 0, 13, 14, 0, 0, 0, 0, - 0, 0, 0, 0, 36, 0, 0, 27, 0, 0, - - 0, 0, 0, 0, 0, 0, 22, 23, 0, 0, - 0, 0, 0, 0, 16, 12, 0, 0, 0, 0, - 0, 0, 0, 30, 0, 18, 25, 0, 0, 0, - 0, 0, 0, 0, 38, 0, 0, 0, 0, 15, + 0, 0, 0, 0, 0, 0, 0, 59, 56, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 35, 0, + 0, 0, 0, 0, 0, 0, 18, 30, 22, 0, + 0, 0, 0, 0, 19, 0, 0, 0, 0, 25, + 26, 38, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 20, 0, 0, 0, 7, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 40, 37, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 21, 16, 0, 0, 0, 0, 0, 32, 34, + 39, 0, 0, 0, 41, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 23, 43, + + 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, + 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, + 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, + 28, 29, 0, 0, 0, 0, 0, 0, 15, 12, + 0, 0, 0, 0, 17, 0, 0, 36, 24, 31, 0 } ; @@ -785,93 +786,95 @@ static const YY_CHAR yy_meta[63] = 3, 3 } ; -static const flex_int16_t yy_base[354] = +static const flex_int16_t yy_base[364] = { 0, 0, 0, 61, 64, 67, 0, 65, 69, 49, 66, - 317, 2235, 86, 312, 129, 0, 108, 2235, 125, 129, - 83, 171, 2235, 291, 90, 81, 81, 86, 2235, 2235, - 97, 119, 123, 2235, 2235, 2235, 153, 288, 251, 0, - 278, 154, 294, 83, 158, 2235, 188, 159, 197, 203, - 214, 222, 238, 244, 259, 265, 273, 279, 302, 308, - 0, 304, 310, 323, 348, 333, 2235, 0, 2235, 339, - 352, 100, 180, 163, 183, 205, 187, 2235, 256, 285, - 2235, 215, 2235, 364, 377, 281, 389, 413, 406, 398, - 442, 455, 461, 467, 476, 482, 496, 503, 511, 517, - - 526, 537, 547, 553, 560, 572, 0, 206, 216, 210, - 224, 237, 232, 236, 2235, 0, 582, 227, 2235, 623, - 596, 608, 616, 2235, 623, 652, 665, 671, 678, 686, - 692, 705, 713, 721, 730, 739, 747, 768, 774, 781, - 788, 245, 2235, 2235, 265, 2235, 2235, 171, 0, 794, - 833, 804, 810, 828, 862, 875, 881, 887, 896, 910, - 916, 925, 931, 940, 950, 960, 975, 984, 990, 996, - 1009, 1020, 2235, 2235, 162, 0, 1032, 1069, 1038, 1054, - 1062, 1068, 1044, 1098, 1115, 1122, 1128, 1134, 1140, 1149, - 1163, 2235, 1157, 1179, 1187, 1193, 1199, 1216, 2235, 2235, - - 1222, 140, 0, 1228, 1237, 1245, 1251, 1262, 2235, 2235, - 2235, 1275, 1281, 1287, 1299, 1310, 1323, 1317, 1333, 1339, - 1346, 1353, 1369, 1375, 1382, 2235, 1388, 1394, 1404, 1418, - 1411, 1424, 1434, 1440, 1454, 1460, 1469, 2235, 2235, 1475, - 1483, 1494, 1504, 1510, 1517, 1529, 1539, 1546, 2235, 1552, - 1558, 1581, 1587, 1595, 2235, 2235, 2235, 1601, 1608, 1621, - 2235, 1630, 1637, 1644, 1655, 1664, 1674, 1680, 1689, 1698, - 1709, 1718, 1725, 1732, 2235, 2235, 1738, 1754, 1761, 1767, - 1775, 1781, 1788, 1797, 2235, 2235, 1811, 1823, 1834, 1840, - 1846, 1852, 1858, 1864, 2235, 1881, 1887, 2235, 1893, 1910, - - 1916, 1922, 1928, 1937, 1945, 1951, 2235, 2235, 1957, 1963, - 1971, 1986, 1992, 2000, 2235, 2235, 2007, 2016, 2022, 2029, - 2036, 2042, 2056, 2235, 2065, 2235, 2235, 2076, 2082, 2090, - 2100, 2106, 2112, 2125, 2235, 2135, 2141, 2148, 2159, 2235, - 2235, 2196, 2201, 2206, 2211, 2216, 2221, 2226, 2229, 157, - 143, 121, 92 + 327, 2297, 86, 320, 129, 0, 108, 2297, 129, 123, + 83, 173, 2297, 297, 90, 81, 81, 90, 2297, 2297, + 125, 95, 105, 2297, 2297, 2297, 113, 302, 244, 0, + 272, 154, 278, 159, 193, 2297, 199, 198, 207, 214, + 220, 254, 262, 270, 276, 288, 299, 305, 311, 328, + 340, 348, 355, 0, 350, 371, 228, 385, 378, 2297, + 0, 2297, 214, 269, 125, 128, 119, 159, 165, 203, + 2297, 241, 219, 2297, 185, 2297, 400, 414, 218, 422, + 450, 444, 478, 493, 434, 499, 505, 512, 518, 534, + + 547, 553, 559, 569, 576, 594, 603, 610, 616, 628, + 637, 657, 663, 0, 208, 219, 193, 244, 272, 234, + 160, 2297, 0, 672, 197, 2297, 713, 678, 697, 684, + 713, 742, 2297, 707, 757, 763, 769, 776, 783, 798, + 792, 817, 827, 836, 851, 861, 873, 880, 888, 895, + 907, 922, 262, 2297, 2297, 291, 2297, 2297, 142, 0, + 929, 968, 936, 965, 946, 995, 1010, 1016, 1022, 1029, + 1040, 1046, 952, 1063, 1069, 1075, 1052, 1081, 1089, 1099, + 1105, 1116, 1123, 1129, 1139, 1146, 1165, 2297, 2297, 121, + 0, 1152, 1189, 1159, 1176, 1182, 1188, 1217, 1232, 1238, + + 1244, 1251, 1257, 1268, 1274, 1280, 1286, 1293, 2297, 1303, + 1315, 1327, 1333, 1341, 1349, 1357, 2297, 2297, 2297, 1363, + 119, 0, 1370, 1378, 2297, 1386, 1397, 1407, 1421, 2297, + 2297, 2297, 1413, 1427, 1434, 1442, 1463, 1469, 1477, 1484, + 1490, 1503, 1511, 2297, 1520, 1527, 1533, 2297, 1545, 1556, + 1562, 1569, 1575, 1586, 1592, 1604, 1610, 1616, 1622, 1629, + 2297, 2297, 1645, 1652, 1658, 1665, 1671, 1679, 1688, 1701, + 1708, 2297, 2297, 1714, 1723, 1738, 1748, 1757, 2297, 2297, + 2297, 1767, 1778, 1786, 2297, 1792, 1802, 1813, 1821, 1831, + 1839, 1847, 1855, 1861, 1876, 1882, 1890, 1897, 2297, 2297, + + 1903, 1919, 1926, 1932, 1940, 1946, 1953, 1962, 2297, 2297, + 1975, 1987, 1999, 2005, 2011, 2021, 2028, 2041, 2297, 2047, + 2055, 2297, 2062, 2076, 2082, 2089, 2100, 2106, 2112, 2118, + 2297, 2297, 2124, 2136, 2153, 2159, 2170, 2176, 2297, 2297, + 2182, 2188, 2194, 2206, 2297, 2217, 2224, 2297, 2297, 2297, + 2297, 2258, 2263, 2268, 2273, 2278, 2283, 2288, 2291, 154, + 121, 92, 84 } ; -static const flex_int16_t yy_def[354] = +static const flex_int16_t yy_def[364] = { 0, - 341, 1, 342, 342, 1, 5, 5, 5, 5, 5, - 341, 341, 341, 341, 343, 344, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, 341, 345, - 341, 341, 341, 346, 343, 341, 343, 347, 343, 343, - 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, - 344, 341, 341, 341, 341, 341, 341, 348, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, 341, 345, - 341, 346, 341, 341, 343, 349, 343, 347, 343, 343, - 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, - - 343, 343, 343, 343, 343, 343, 348, 341, 341, 341, - 341, 341, 341, 341, 341, 350, 343, 349, 341, 347, - 343, 343, 343, 341, 343, 343, 343, 343, 343, 343, - 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, - 343, 341, 341, 341, 341, 341, 341, 341, 351, 343, - 347, 343, 343, 343, 343, 343, 343, 343, 343, 343, - 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, - 343, 343, 341, 341, 341, 352, 343, 347, 343, 343, - 343, 343, 343, 343, 343, 343, 343, 343, 343, 343, - 343, 341, 343, 343, 343, 343, 343, 343, 341, 341, - - 343, 341, 353, 343, 343, 343, 343, 343, 341, 341, - 341, 343, 343, 343, 343, 343, 343, 343, 343, 343, - 343, 343, 343, 343, 343, 341, 343, 343, 343, 343, - 343, 343, 343, 343, 343, 343, 343, 341, 341, 343, - 343, 343, 343, 343, 343, 343, 343, 343, 341, 343, - 343, 343, 343, 343, 341, 341, 341, 343, 343, 343, - 341, 343, 343, 343, 343, 343, 343, 343, 343, 343, - 343, 343, 343, 343, 341, 341, 343, 343, 343, 343, - 343, 343, 343, 343, 341, 341, 343, 343, 343, 343, - 343, 343, 343, 343, 341, 343, 343, 341, 343, 343, - - 343, 343, 343, 343, 343, 343, 341, 341, 343, 343, - 343, 343, 343, 343, 341, 341, 343, 343, 343, 343, - 343, 343, 343, 341, 343, 341, 341, 343, 343, 343, - 343, 343, 343, 343, 341, 343, 343, 343, 343, 341, - 0, 341, 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341 + 351, 1, 352, 352, 1, 5, 5, 5, 5, 5, + 351, 351, 351, 351, 353, 354, 351, 351, 351, 351, + 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, + 351, 351, 351, 351, 351, 351, 351, 351, 351, 355, + 351, 351, 351, 356, 353, 351, 353, 357, 353, 353, + 353, 353, 353, 353, 353, 353, 353, 353, 353, 353, + 353, 353, 353, 354, 351, 351, 351, 351, 351, 351, + 358, 351, 351, 351, 351, 351, 351, 351, 351, 351, + 351, 351, 355, 351, 356, 351, 351, 353, 359, 353, + 357, 353, 353, 353, 353, 353, 353, 353, 353, 353, + + 353, 353, 353, 353, 353, 353, 353, 353, 353, 353, + 353, 353, 353, 358, 351, 351, 351, 351, 351, 351, + 351, 351, 360, 353, 359, 351, 357, 353, 353, 353, + 353, 353, 351, 353, 353, 353, 353, 353, 353, 353, + 353, 353, 353, 353, 353, 353, 353, 353, 353, 353, + 353, 353, 351, 351, 351, 351, 351, 351, 351, 361, + 353, 357, 353, 353, 353, 353, 353, 353, 353, 353, + 353, 353, 353, 353, 353, 353, 353, 353, 353, 353, + 353, 353, 353, 353, 353, 353, 353, 351, 351, 351, + 362, 353, 357, 353, 353, 353, 353, 353, 353, 353, + + 353, 353, 353, 353, 353, 353, 353, 353, 351, 353, + 353, 353, 353, 353, 353, 353, 351, 351, 351, 353, + 351, 363, 353, 353, 351, 353, 353, 353, 353, 351, + 351, 351, 353, 353, 353, 353, 353, 353, 353, 353, + 353, 353, 353, 351, 353, 353, 353, 351, 353, 353, + 353, 353, 353, 353, 353, 353, 353, 353, 353, 353, + 351, 351, 353, 353, 353, 353, 353, 353, 353, 353, + 353, 351, 351, 353, 353, 353, 353, 353, 351, 351, + 351, 353, 353, 353, 351, 353, 353, 353, 353, 353, + 353, 353, 353, 353, 353, 353, 353, 353, 351, 351, + + 353, 353, 353, 353, 353, 353, 353, 353, 351, 351, + 353, 353, 353, 353, 353, 353, 353, 353, 351, 353, + 353, 351, 353, 353, 353, 353, 353, 353, 353, 353, + 351, 351, 353, 353, 353, 353, 353, 353, 351, 351, + 353, 353, 353, 353, 351, 353, 353, 351, 351, 351, + 0, 351, 351, 351, 351, 351, 351, 351, 351, 351, + 351, 351, 351 } ; -static const flex_int16_t yy_nxt[2298] = +static const flex_int16_t yy_nxt[2360] = { 0, 12, 13, 14, 13, 12, 15, 16, 12, 17, 18, 19, 20, 21, 22, 22, 22, 22, 23, 24, 12, @@ -881,254 +884,260 @@ static const flex_int16_t yy_nxt[2298] = 12, 12, 12, 33, 12, 12, 12, 12, 12, 12, 34, 35, 37, 14, 37, 37, 14, 37, 38, 41, 40, 38, 12, 12, 40, 12, 12, 12, 12, 12, - 12, 12, 12, 12, 12, 12, 41, 42, 83, 42, - 67, 12, 12, 12, 12, 68, 82, 12, 70, 12, - - 70, 12, 72, 71, 71, 71, 71, 12, 12, 12, - 12, 39, 73, 12, 74, 12, 84, 72, 72, 62, - 12, 63, 63, 63, 63, 203, 108, 12, 12, 44, - 44, 44, 64, 75, 46, 73, 62, 74, 65, 65, - 65, 65, 66, 66, 66, 66, 108, 176, 64, 64, - 73, 74, 47, 64, 42, 42, 42, 42, 44, 44, - 44, 149, 48, 46, 87, 64, 49, 50, 51, 64, - 52, 45, 53, 76, 77, 54, 55, 56, 57, 58, - 226, 59, 62, 60, 65, 65, 65, 65, 44, 44, - 44, 48, 45, 46, 110, 64, 45, 44, 44, 44, - - 45, 202, 46, 44, 44, 44, 109, 45, 46, 108, - 45, 64, 45, 88, 44, 44, 44, 110, 110, 46, - 83, 48, 44, 44, 44, 175, 109, 46, 91, 111, - 48, 109, 119, 89, 144, 142, 48, 85, 44, 44, - 44, 113, 143, 46, 44, 44, 44, 48, 84, 46, - 144, 112, 90, 142, 92, 48, 144, 93, 142, 44, - 44, 44, 143, 143, 46, 44, 44, 44, 94, 173, - 46, 48, 147, 44, 44, 44, 145, 48, 46, 44, - 44, 44, 148, 146, 46, 173, 119, 95, 97, 173, - 115, 96, 48, 98, 114, 99, 43, 81, 48, 79, - - 78, 100, 44, 44, 44, 174, 48, 46, 44, 44, - 44, 69, 48, 46, 43, 102, 341, 66, 66, 66, - 66, 62, 341, 63, 63, 63, 63, 101, 64, 341, - 341, 70, 341, 70, 64, 48, 71, 71, 71, 71, - 341, 48, 103, 341, 64, 341, 66, 66, 66, 66, - 64, 104, 71, 71, 71, 71, 105, 64, 341, 62, - 106, 65, 65, 65, 65, 71, 71, 71, 71, 82, - 341, 341, 64, 64, 341, 341, 82, 44, 44, 44, - 341, 341, 46, 341, 341, 341, 341, 341, 64, 44, - 44, 44, 341, 341, 46, 341, 341, 82, 44, 44, - - 44, 82, 341, 46, 341, 82, 44, 44, 44, 341, - 48, 46, 82, 341, 341, 82, 341, 82, 116, 341, - 341, 341, 48, 341, 341, 117, 120, 120, 120, 120, - 341, 48, 341, 341, 120, 120, 120, 120, 120, 48, - 341, 341, 44, 44, 44, 122, 123, 124, 341, 120, - 120, 120, 120, 120, 120, 44, 44, 44, 121, 341, - 46, 44, 44, 44, 341, 341, 46, 44, 44, 44, - 341, 341, 46, 341, 341, 48, 44, 44, 44, 341, - 341, 46, 44, 44, 44, 341, 341, 46, 48, 341, - 341, 341, 125, 341, 48, 341, 44, 44, 44, 126, - - 48, 46, 341, 44, 44, 44, 341, 341, 46, 48, - 341, 44, 44, 44, 341, 48, 46, 44, 44, 44, - 341, 127, 46, 341, 341, 128, 44, 44, 44, 48, - 341, 46, 341, 130, 341, 129, 48, 44, 44, 44, - 341, 341, 46, 341, 48, 131, 341, 44, 44, 44, - 48, 341, 46, 44, 44, 44, 341, 341, 46, 48, - 44, 44, 44, 341, 133, 46, 341, 341, 132, 341, - 48, 341, 44, 44, 44, 341, 341, 46, 341, 134, - 48, 341, 44, 44, 44, 341, 48, 46, 135, 136, - 137, 139, 341, 48, 341, 341, 44, 44, 44, 341, - - 341, 46, 138, 341, 140, 48, 341, 341, 44, 44, - 44, 341, 141, 46, 341, 48, 44, 44, 44, 341, - 341, 46, 341, 44, 44, 44, 341, 341, 46, 48, - 341, 341, 341, 341, 341, 150, 151, 151, 151, 151, - 152, 48, 341, 341, 151, 151, 151, 151, 151, 48, - 341, 341, 44, 44, 44, 153, 48, 46, 341, 151, - 151, 151, 151, 151, 151, 44, 44, 44, 341, 154, - 46, 44, 44, 44, 341, 341, 46, 155, 44, 44, - 44, 341, 341, 46, 341, 48, 44, 44, 44, 341, - 341, 46, 44, 44, 44, 341, 341, 46, 48, 341, - - 341, 341, 156, 341, 48, 44, 44, 44, 341, 341, - 46, 48, 341, 44, 44, 44, 158, 157, 46, 48, - 341, 44, 44, 44, 341, 48, 46, 341, 159, 341, - 44, 44, 44, 341, 161, 46, 341, 160, 48, 44, - 44, 44, 341, 341, 46, 341, 48, 44, 44, 44, - 341, 341, 46, 164, 48, 341, 341, 162, 341, 341, - 163, 341, 341, 48, 341, 341, 166, 341, 44, 44, - 44, 165, 48, 46, 44, 44, 44, 341, 341, 46, - 48, 44, 44, 44, 341, 341, 46, 341, 44, 44, - 44, 167, 341, 46, 44, 44, 44, 341, 341, 46, - - 168, 48, 341, 341, 44, 44, 44, 48, 169, 46, - 44, 44, 44, 341, 48, 46, 341, 341, 341, 170, - 341, 48, 341, 341, 341, 341, 341, 48, 44, 44, - 44, 341, 341, 46, 341, 341, 341, 48, 171, 172, - 341, 341, 179, 48, 341, 177, 178, 178, 178, 178, - 180, 341, 341, 341, 178, 178, 178, 178, 178, 341, - 341, 48, 44, 44, 44, 341, 341, 46, 341, 178, - 178, 178, 178, 178, 178, 44, 44, 44, 341, 181, - 46, 44, 44, 44, 341, 341, 46, 44, 44, 44, - 183, 184, 46, 341, 341, 48, 44, 44, 44, 341, - - 341, 46, 341, 341, 182, 341, 187, 341, 48, 341, - 44, 44, 44, 341, 48, 46, 44, 44, 44, 341, - 48, 46, 341, 341, 185, 44, 44, 44, 341, 48, - 46, 44, 44, 44, 341, 341, 46, 341, 341, 186, - 44, 44, 44, 48, 341, 192, 188, 341, 341, 48, - 44, 44, 44, 341, 341, 46, 189, 341, 48, 341, - 44, 44, 44, 341, 48, 46, 341, 341, 341, 190, - 341, 191, 341, 48, 341, 44, 44, 44, 341, 341, - 46, 341, 341, 48, 44, 44, 44, 341, 341, 46, - 44, 44, 44, 48, 341, 46, 44, 44, 44, 341, - - 341, 46, 341, 341, 193, 341, 341, 194, 48, 44, - 44, 44, 341, 341, 199, 341, 341, 48, 341, 341, - 44, 44, 44, 48, 196, 200, 341, 341, 341, 48, - 201, 195, 44, 44, 44, 341, 198, 46, 44, 44, - 44, 197, 48, 46, 44, 44, 44, 341, 205, 209, - 341, 341, 341, 48, 44, 44, 44, 341, 341, 46, - 341, 341, 44, 44, 44, 48, 341, 46, 44, 44, - 44, 48, 341, 46, 341, 341, 341, 48, 341, 341, - 341, 204, 45, 45, 45, 45, 341, 48, 341, 341, - 45, 45, 45, 45, 45, 48, 341, 341, 44, 44, - - 44, 48, 206, 210, 341, 45, 45, 45, 45, 45, - 45, 207, 341, 341, 208, 44, 44, 44, 341, 341, - 211, 341, 44, 44, 44, 341, 341, 46, 44, 44, - 44, 48, 212, 46, 44, 44, 44, 341, 341, 46, - 44, 44, 44, 341, 341, 46, 341, 341, 48, 44, - 44, 44, 341, 341, 46, 48, 341, 44, 44, 44, - 341, 48, 46, 44, 44, 44, 341, 48, 46, 341, - 341, 213, 341, 48, 341, 341, 341, 341, 214, 44, - 44, 44, 48, 341, 46, 215, 341, 44, 44, 44, - 48, 216, 46, 44, 44, 44, 48, 341, 46, 44, - - 44, 44, 341, 341, 46, 341, 341, 341, 217, 341, - 219, 341, 48, 341, 218, 341, 44, 44, 44, 220, - 48, 46, 44, 44, 44, 341, 48, 46, 44, 44, - 44, 341, 48, 46, 341, 341, 221, 44, 44, 44, - 341, 341, 46, 223, 222, 44, 44, 44, 341, 48, - 46, 44, 44, 44, 341, 48, 46, 341, 341, 341, - 225, 48, 44, 44, 44, 341, 341, 46, 341, 224, - 48, 341, 341, 228, 227, 44, 44, 44, 48, 341, - 46, 44, 44, 44, 48, 341, 46, 44, 44, 44, - 341, 341, 46, 341, 341, 48, 341, 230, 229, 44, - - 44, 44, 231, 341, 46, 341, 341, 341, 48, 341, - 44, 44, 44, 341, 48, 46, 341, 44, 44, 44, - 48, 232, 238, 44, 44, 44, 341, 341, 46, 341, - 233, 341, 48, 44, 44, 44, 234, 341, 239, 44, - 44, 44, 341, 48, 46, 341, 44, 44, 44, 341, - 48, 46, 341, 44, 44, 44, 48, 235, 46, 341, - 341, 341, 236, 237, 341, 341, 48, 341, 240, 44, - 44, 44, 48, 341, 46, 44, 44, 44, 341, 48, - 46, 341, 44, 44, 44, 245, 48, 46, 44, 44, - 44, 341, 241, 46, 44, 44, 44, 242, 247, 46, - - 341, 243, 48, 341, 44, 44, 44, 341, 48, 249, - 341, 44, 44, 44, 341, 48, 46, 341, 44, 44, - 44, 48, 244, 46, 44, 44, 44, 48, 250, 46, - 341, 246, 341, 341, 44, 44, 44, 48, 341, 46, - 44, 44, 44, 341, 48, 46, 341, 341, 248, 341, - 341, 48, 341, 341, 44, 44, 44, 48, 341, 255, - 44, 44, 44, 341, 341, 256, 251, 48, 252, 44, - 44, 44, 341, 48, 257, 44, 44, 44, 341, 341, - 46, 341, 341, 44, 44, 44, 253, 48, 46, 341, - 341, 254, 341, 48, 44, 44, 44, 341, 341, 46, - - 341, 341, 48, 341, 44, 44, 44, 341, 48, 261, - 44, 44, 44, 341, 341, 46, 48, 44, 44, 44, - 341, 341, 46, 259, 258, 341, 341, 48, 341, 44, - 44, 44, 341, 260, 46, 341, 341, 48, 341, 44, - 44, 44, 341, 48, 46, 341, 44, 44, 44, 341, - 48, 46, 44, 44, 44, 341, 341, 46, 44, 44, - 44, 341, 48, 46, 341, 263, 341, 341, 262, 341, - 264, 341, 48, 341, 341, 266, 341, 265, 341, 48, - 341, 44, 44, 44, 341, 48, 46, 44, 44, 44, - 341, 48, 46, 341, 341, 44, 44, 44, 269, 267, - - 46, 44, 44, 44, 268, 341, 46, 341, 44, 44, - 44, 341, 341, 46, 48, 341, 341, 341, 270, 341, - 48, 44, 44, 44, 341, 341, 275, 341, 48, 341, - 44, 44, 44, 341, 48, 276, 341, 44, 44, 44, - 271, 48, 46, 341, 44, 44, 44, 341, 272, 46, - 341, 273, 341, 341, 48, 44, 44, 44, 341, 274, - 46, 341, 341, 48, 44, 44, 44, 341, 341, 46, - 48, 341, 341, 277, 44, 44, 44, 48, 341, 46, - 44, 44, 44, 341, 341, 46, 341, 341, 48, 44, - 44, 44, 341, 341, 46, 341, 341, 48, 44, 44, - - 44, 341, 278, 46, 341, 341, 280, 48, 279, 44, - 44, 44, 341, 48, 285, 341, 341, 281, 44, 44, - 44, 341, 48, 286, 341, 44, 44, 44, 341, 282, - 46, 48, 44, 44, 44, 283, 341, 46, 44, 44, - 44, 341, 48, 46, 341, 341, 341, 341, 341, 284, - 341, 48, 341, 341, 44, 44, 44, 341, 48, 46, - 341, 44, 44, 44, 341, 48, 46, 44, 44, 44, - 341, 48, 46, 341, 341, 44, 44, 44, 287, 341, - 46, 44, 44, 44, 288, 289, 46, 48, 44, 44, - 44, 341, 341, 295, 48, 341, 341, 44, 44, 44, - - 48, 291, 46, 341, 290, 341, 341, 292, 48, 341, - 341, 44, 44, 44, 48, 293, 46, 341, 341, 294, - 341, 48, 341, 44, 44, 44, 341, 341, 298, 341, - 48, 341, 341, 296, 44, 44, 44, 341, 341, 46, - 44, 44, 44, 341, 48, 46, 44, 44, 44, 341, - 341, 46, 44, 44, 44, 297, 48, 46, 44, 44, - 44, 341, 341, 46, 44, 44, 44, 48, 341, 46, - 341, 341, 341, 48, 299, 341, 341, 341, 341, 48, - 300, 44, 44, 44, 341, 48, 46, 44, 44, 44, - 341, 48, 46, 44, 44, 44, 341, 48, 307, 341, - - 302, 341, 341, 301, 341, 341, 303, 341, 341, 304, - 44, 44, 44, 341, 48, 308, 44, 44, 44, 341, - 48, 46, 44, 44, 44, 341, 48, 46, 44, 44, - 44, 341, 305, 46, 341, 341, 306, 44, 44, 44, - 341, 341, 46, 48, 341, 44, 44, 44, 341, 48, - 46, 44, 44, 44, 341, 48, 46, 44, 44, 44, - 341, 48, 315, 44, 44, 44, 341, 341, 316, 309, - 48, 44, 44, 44, 341, 310, 46, 312, 48, 341, - 341, 311, 341, 341, 48, 341, 44, 44, 44, 313, - 48, 46, 44, 44, 44, 341, 48, 46, 341, 314, - - 44, 44, 44, 341, 48, 46, 341, 44, 44, 44, - 341, 341, 46, 341, 341, 317, 44, 44, 44, 48, - 341, 46, 44, 44, 44, 48, 341, 46, 341, 44, - 44, 44, 319, 48, 324, 341, 44, 44, 44, 318, - 48, 46, 44, 44, 44, 321, 341, 326, 341, 48, - 341, 341, 320, 341, 341, 48, 44, 44, 44, 341, - 341, 327, 48, 341, 341, 44, 44, 44, 322, 48, - 46, 341, 325, 341, 323, 48, 44, 44, 44, 341, - 341, 46, 44, 44, 44, 341, 341, 46, 341, 48, - 44, 44, 44, 341, 341, 46, 341, 341, 48, 341, - - 44, 44, 44, 341, 341, 46, 44, 44, 44, 48, - 332, 46, 44, 44, 44, 48, 341, 335, 328, 341, - 329, 341, 341, 48, 341, 44, 44, 44, 341, 341, - 46, 330, 341, 48, 341, 44, 44, 44, 331, 48, - 46, 44, 44, 44, 341, 48, 46, 341, 44, 44, - 44, 341, 333, 46, 341, 341, 341, 334, 48, 44, - 44, 44, 341, 341, 340, 336, 341, 341, 48, 341, - 341, 337, 341, 341, 48, 341, 341, 341, 341, 341, - 341, 48, 341, 341, 341, 341, 341, 338, 341, 341, - 341, 341, 48, 341, 341, 339, 36, 36, 36, 36, - - 36, 45, 45, 45, 45, 45, 61, 341, 61, 61, - 61, 80, 341, 80, 341, 80, 82, 82, 82, 82, - 82, 86, 86, 86, 86, 86, 107, 341, 107, 107, - 107, 118, 118, 118, 11, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341 - + 12, 12, 12, 12, 12, 12, 41, 42, 85, 42, + 70, 12, 12, 12, 12, 71, 222, 12, 73, 12, + + 73, 12, 75, 74, 74, 74, 74, 12, 12, 12, + 12, 39, 76, 12, 42, 12, 42, 75, 77, 65, + 12, 66, 66, 66, 66, 191, 76, 12, 12, 44, + 44, 44, 67, 77, 46, 76, 69, 69, 69, 69, + 65, 77, 68, 68, 68, 68, 75, 67, 67, 79, + 117, 115, 47, 67, 116, 42, 80, 42, 160, 248, + 221, 78, 48, 67, 86, 49, 50, 51, 52, 67, + 53, 115, 54, 117, 116, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 65, 115, 68, 68, 68, 68, + 86, 116, 87, 44, 44, 44, 190, 67, 46, 44, + + 44, 44, 126, 90, 46, 118, 159, 44, 44, 44, + 45, 119, 46, 67, 44, 44, 44, 155, 87, 46, + 44, 44, 44, 126, 122, 46, 48, 74, 74, 74, + 74, 45, 48, 155, 117, 45, 73, 153, 73, 45, + 48, 74, 74, 74, 74, 154, 45, 48, 88, 45, + 93, 45, 91, 48, 44, 44, 44, 120, 155, 46, + 153, 92, 44, 44, 44, 154, 94, 46, 96, 95, + 44, 44, 44, 153, 158, 46, 44, 44, 44, 121, + 43, 46, 74, 74, 74, 74, 188, 48, 44, 44, + 44, 84, 82, 46, 97, 48, 156, 98, 154, 44, + + 44, 44, 188, 48, 46, 44, 44, 44, 99, 48, + 46, 44, 44, 44, 81, 188, 46, 72, 157, 100, + 102, 48, 43, 101, 104, 103, 351, 351, 44, 44, + 44, 189, 48, 46, 351, 105, 351, 351, 48, 351, + 44, 44, 44, 351, 48, 46, 351, 107, 44, 44, + 44, 351, 351, 46, 351, 44, 44, 44, 351, 106, + 46, 48, 351, 69, 69, 69, 69, 351, 108, 351, + 351, 351, 351, 48, 67, 351, 351, 351, 351, 351, + 109, 48, 65, 351, 66, 66, 66, 66, 48, 110, + 67, 69, 69, 69, 69, 67, 65, 351, 68, 68, + + 68, 68, 67, 112, 351, 85, 111, 113, 351, 67, + 351, 67, 85, 351, 44, 44, 44, 351, 67, 46, + 351, 351, 44, 44, 44, 67, 351, 46, 351, 351, + 351, 351, 351, 85, 44, 44, 44, 85, 351, 46, + 351, 85, 351, 351, 44, 44, 44, 48, 85, 46, + 351, 85, 351, 85, 123, 48, 351, 351, 351, 351, + 351, 351, 124, 127, 127, 127, 127, 48, 351, 351, + 351, 127, 127, 127, 127, 127, 351, 48, 44, 44, + 44, 131, 132, 46, 351, 351, 127, 127, 127, 127, + 127, 127, 351, 44, 44, 44, 351, 128, 46, 44, + + 44, 44, 351, 351, 133, 44, 44, 44, 351, 351, + 46, 48, 44, 44, 44, 351, 351, 46, 44, 44, + 44, 351, 351, 46, 351, 351, 48, 351, 351, 351, + 129, 351, 48, 351, 44, 44, 44, 130, 48, 46, + 351, 351, 134, 351, 351, 48, 351, 44, 44, 44, + 135, 48, 46, 44, 44, 44, 351, 351, 46, 44, + 44, 44, 351, 351, 46, 351, 351, 48, 351, 44, + 44, 44, 136, 351, 46, 351, 44, 44, 44, 351, + 48, 46, 351, 137, 351, 351, 48, 351, 351, 351, + 139, 351, 48, 351, 44, 44, 44, 351, 351, 46, + + 138, 140, 48, 44, 44, 44, 351, 351, 46, 48, + 44, 44, 44, 351, 351, 46, 44, 44, 44, 351, + 351, 46, 351, 142, 351, 351, 141, 48, 44, 44, + 44, 351, 351, 46, 351, 351, 48, 44, 44, 44, + 351, 351, 46, 48, 351, 351, 147, 143, 351, 48, + 351, 351, 351, 351, 144, 145, 146, 44, 44, 44, + 351, 48, 46, 44, 44, 44, 149, 351, 46, 351, + 48, 148, 44, 44, 44, 351, 351, 46, 44, 44, + 44, 351, 351, 46, 44, 44, 44, 150, 351, 46, + 48, 351, 351, 351, 351, 351, 48, 44, 44, 44, + + 351, 151, 46, 152, 351, 48, 351, 44, 44, 44, + 351, 48, 46, 44, 44, 44, 351, 48, 46, 351, + 351, 163, 351, 351, 165, 161, 162, 162, 162, 162, + 48, 351, 351, 351, 162, 162, 162, 162, 162, 351, + 48, 164, 44, 44, 44, 351, 48, 46, 351, 162, + 162, 162, 162, 162, 162, 351, 351, 44, 44, 44, + 166, 168, 46, 44, 44, 44, 351, 351, 46, 44, + 44, 44, 351, 351, 46, 48, 44, 44, 44, 351, + 351, 46, 351, 44, 44, 44, 351, 351, 46, 351, + 48, 351, 44, 44, 44, 167, 48, 46, 44, 44, + + 44, 351, 48, 46, 351, 351, 351, 169, 351, 48, + 351, 351, 351, 351, 171, 170, 48, 44, 44, 44, + 351, 351, 46, 351, 351, 48, 172, 44, 44, 44, + 351, 48, 46, 351, 173, 351, 44, 44, 44, 351, + 174, 46, 351, 351, 175, 351, 351, 176, 351, 351, + 48, 44, 44, 44, 351, 351, 46, 177, 351, 351, + 48, 44, 44, 44, 351, 351, 46, 351, 351, 48, + 351, 351, 179, 44, 44, 44, 351, 178, 46, 351, + 44, 44, 44, 351, 48, 46, 351, 351, 44, 44, + 44, 351, 351, 46, 48, 44, 44, 44, 351, 351, + + 46, 351, 351, 180, 351, 351, 48, 44, 44, 44, + 351, 351, 46, 48, 181, 351, 351, 351, 351, 182, + 183, 48, 44, 44, 44, 351, 351, 46, 48, 44, + 44, 44, 351, 184, 46, 185, 44, 44, 44, 351, + 48, 46, 351, 351, 351, 351, 44, 44, 44, 351, + 351, 46, 44, 44, 44, 48, 351, 46, 351, 351, + 351, 351, 48, 351, 186, 44, 44, 44, 351, 48, + 46, 351, 351, 187, 351, 351, 194, 351, 351, 48, + 192, 193, 193, 193, 193, 48, 351, 351, 205, 193, + 193, 193, 193, 193, 196, 44, 44, 44, 48, 351, + + 46, 351, 351, 195, 193, 193, 193, 193, 193, 193, + 44, 44, 44, 351, 351, 46, 44, 44, 44, 351, + 351, 46, 44, 44, 44, 351, 351, 46, 48, 44, + 44, 44, 351, 351, 46, 197, 351, 200, 201, 351, + 44, 44, 44, 48, 351, 46, 44, 44, 44, 48, + 351, 46, 44, 44, 44, 48, 204, 209, 199, 351, + 351, 198, 48, 44, 44, 44, 351, 351, 46, 44, + 44, 44, 202, 48, 46, 44, 44, 44, 351, 48, + 46, 44, 44, 44, 351, 48, 46, 351, 351, 44, + 44, 44, 203, 351, 46, 351, 48, 351, 351, 44, + + 44, 44, 48, 206, 46, 44, 44, 44, 48, 351, + 46, 351, 351, 207, 48, 208, 44, 44, 44, 351, + 351, 46, 48, 44, 44, 44, 351, 351, 46, 44, + 44, 44, 48, 351, 46, 210, 211, 351, 48, 44, + 44, 44, 351, 351, 217, 213, 44, 44, 44, 48, + 351, 218, 44, 44, 44, 212, 48, 46, 351, 44, + 44, 44, 48, 214, 46, 44, 44, 44, 351, 216, + 219, 351, 48, 351, 215, 220, 44, 44, 44, 48, + 351, 225, 44, 44, 44, 48, 351, 46, 44, 44, + 44, 351, 48, 46, 351, 351, 351, 351, 48, 351, + + 351, 223, 45, 45, 45, 45, 351, 224, 351, 48, + 45, 45, 45, 45, 45, 48, 351, 44, 44, 44, + 351, 48, 46, 351, 351, 45, 45, 45, 45, 45, + 45, 351, 44, 44, 44, 226, 227, 46, 44, 44, + 44, 351, 351, 230, 44, 44, 44, 351, 351, 231, + 48, 44, 44, 44, 351, 351, 232, 44, 44, 44, + 351, 351, 46, 351, 351, 48, 228, 233, 44, 44, + 44, 48, 351, 46, 44, 44, 44, 48, 229, 46, + 44, 44, 44, 351, 48, 46, 44, 44, 44, 351, + 48, 46, 351, 44, 44, 44, 351, 351, 46, 351, + + 351, 48, 351, 44, 44, 44, 351, 48, 46, 351, + 351, 234, 351, 48, 351, 44, 44, 44, 235, 48, + 46, 351, 351, 351, 351, 236, 48, 44, 44, 44, + 351, 237, 46, 44, 44, 44, 48, 351, 46, 351, + 351, 44, 44, 44, 239, 238, 244, 351, 48, 44, + 44, 44, 351, 351, 46, 241, 240, 44, 44, 44, + 48, 351, 46, 44, 44, 44, 48, 351, 46, 351, + 44, 44, 44, 351, 48, 46, 242, 351, 44, 44, + 44, 351, 48, 46, 243, 351, 44, 44, 44, 351, + 48, 46, 351, 245, 351, 351, 48, 44, 44, 44, + + 351, 247, 46, 48, 351, 351, 351, 44, 44, 44, + 246, 48, 46, 44, 44, 44, 249, 351, 46, 48, + 351, 44, 44, 44, 351, 351, 46, 44, 44, 44, + 48, 250, 46, 351, 44, 44, 44, 351, 251, 46, + 48, 351, 44, 44, 44, 351, 48, 46, 351, 351, + 252, 351, 351, 253, 48, 351, 351, 351, 351, 255, + 48, 254, 351, 44, 44, 44, 351, 48, 46, 44, + 44, 44, 351, 351, 46, 48, 256, 44, 44, 44, + 351, 351, 261, 257, 44, 44, 44, 351, 351, 262, + 44, 44, 44, 351, 351, 46, 48, 351, 351, 351, + + 258, 351, 48, 44, 44, 44, 351, 351, 46, 260, + 48, 44, 44, 44, 351, 259, 46, 48, 351, 263, + 44, 44, 44, 48, 351, 46, 351, 44, 44, 44, + 351, 351, 46, 44, 44, 44, 48, 268, 46, 351, + 351, 351, 351, 264, 48, 44, 44, 44, 351, 351, + 46, 351, 351, 48, 265, 270, 44, 44, 44, 266, + 48, 46, 44, 44, 44, 351, 48, 272, 351, 44, + 44, 44, 351, 267, 273, 44, 44, 44, 48, 351, + 46, 351, 269, 351, 351, 274, 44, 44, 44, 48, + 351, 46, 44, 44, 44, 48, 351, 46, 351, 351, + + 271, 351, 48, 351, 44, 44, 44, 351, 48, 46, + 44, 44, 44, 351, 351, 46, 44, 44, 44, 48, + 351, 279, 44, 44, 44, 48, 351, 280, 351, 44, + 44, 44, 351, 351, 281, 351, 276, 48, 351, 351, + 351, 275, 351, 48, 351, 44, 44, 44, 351, 48, + 46, 351, 44, 44, 44, 48, 277, 46, 44, 44, + 44, 278, 48, 46, 351, 44, 44, 44, 351, 351, + 285, 44, 44, 44, 351, 351, 46, 351, 48, 44, + 44, 44, 351, 351, 46, 48, 351, 351, 44, 44, + 44, 48, 283, 46, 282, 351, 351, 284, 48, 351, + + 351, 44, 44, 44, 48, 351, 46, 351, 44, 44, + 44, 351, 48, 46, 44, 44, 44, 351, 351, 46, + 351, 48, 351, 44, 44, 44, 351, 287, 46, 286, + 351, 351, 288, 351, 48, 351, 289, 290, 44, 44, + 44, 48, 351, 46, 351, 351, 291, 48, 44, 44, + 44, 351, 351, 46, 351, 351, 48, 44, 44, 44, + 351, 351, 46, 293, 351, 351, 292, 44, 44, 44, + 351, 48, 46, 351, 351, 294, 351, 351, 44, 44, + 44, 48, 351, 46, 351, 351, 44, 44, 44, 351, + 48, 299, 44, 44, 44, 351, 351, 300, 351, 351, + + 48, 295, 44, 44, 44, 351, 351, 46, 351, 351, + 296, 48, 351, 44, 44, 44, 351, 297, 46, 48, + 351, 44, 44, 44, 351, 48, 46, 351, 351, 298, + 351, 44, 44, 44, 351, 48, 46, 351, 301, 44, + 44, 44, 351, 351, 46, 351, 48, 44, 44, 44, + 351, 351, 46, 351, 48, 44, 44, 44, 351, 351, + 46, 44, 44, 44, 48, 351, 46, 351, 351, 351, + 351, 302, 48, 304, 303, 305, 44, 44, 44, 351, + 48, 309, 44, 44, 44, 351, 351, 310, 48, 351, + 44, 44, 44, 351, 48, 46, 306, 44, 44, 44, + + 351, 307, 46, 44, 44, 44, 351, 351, 46, 48, + 351, 351, 308, 351, 351, 48, 351, 351, 351, 44, + 44, 44, 351, 48, 46, 351, 44, 44, 44, 351, + 48, 46, 44, 44, 44, 351, 48, 46, 351, 351, + 44, 44, 44, 311, 351, 46, 44, 44, 44, 312, + 313, 46, 48, 44, 44, 44, 351, 351, 319, 48, + 351, 351, 44, 44, 44, 48, 315, 46, 351, 314, + 351, 351, 316, 48, 351, 44, 44, 44, 351, 48, + 46, 351, 351, 351, 318, 351, 48, 44, 44, 44, + 351, 351, 322, 317, 351, 48, 351, 351, 320, 44, + + 44, 44, 351, 351, 46, 44, 44, 44, 48, 351, + 46, 44, 44, 44, 351, 351, 46, 351, 351, 321, + 48, 44, 44, 44, 351, 351, 46, 351, 44, 44, + 44, 351, 48, 46, 351, 351, 351, 351, 48, 323, + 351, 44, 44, 44, 48, 324, 46, 44, 44, 44, + 351, 351, 46, 351, 48, 44, 44, 44, 351, 351, + 46, 48, 44, 44, 44, 351, 351, 331, 325, 326, + 351, 351, 327, 351, 48, 351, 44, 44, 44, 351, + 48, 332, 44, 44, 44, 351, 328, 46, 48, 44, + 44, 44, 351, 351, 46, 48, 351, 351, 329, 351, + + 44, 44, 44, 351, 330, 46, 44, 44, 44, 48, + 351, 46, 44, 44, 44, 48, 351, 46, 44, 44, + 44, 351, 48, 46, 44, 44, 44, 351, 351, 339, + 351, 351, 351, 48, 351, 333, 44, 44, 44, 48, + 351, 340, 334, 351, 351, 48, 336, 351, 351, 335, + 351, 48, 351, 44, 44, 44, 337, 48, 46, 44, + 44, 44, 351, 351, 46, 351, 338, 351, 351, 48, + 44, 44, 44, 351, 351, 46, 44, 44, 44, 351, + 351, 46, 44, 44, 44, 351, 48, 345, 44, 44, + 44, 351, 48, 46, 44, 44, 44, 351, 351, 46, + + 351, 341, 351, 48, 351, 351, 44, 44, 44, 48, + 343, 348, 342, 351, 351, 48, 351, 44, 44, 44, + 351, 48, 349, 351, 44, 44, 44, 48, 344, 350, + 351, 351, 351, 351, 351, 351, 351, 351, 351, 48, + 346, 351, 351, 351, 351, 351, 347, 351, 351, 351, + 48, 351, 351, 351, 351, 351, 351, 48, 36, 36, + 36, 36, 36, 45, 45, 45, 45, 45, 64, 351, + 64, 64, 64, 83, 351, 83, 351, 83, 85, 85, + 85, 85, 85, 89, 89, 89, 89, 89, 114, 351, + 114, 114, 114, 125, 125, 125, 11, 351, 351, 351, + + 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, + 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, + 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, + 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, + 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, + 351, 351, 351, 351, 351, 351, 351, 351, 351 } ; -static const flex_int16_t yy_chk[2298] = +static const flex_int16_t yy_chk[2360] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -1138,251 +1147,257 @@ static const flex_int16_t yy_chk[2298] = 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 4, 4, 4, 3, 9, 7, 4, 5, 5, 8, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 10, 13, 44, 13, - 21, 5, 5, 9, 5, 21, 353, 5, 25, 5, + 5, 5, 5, 5, 5, 5, 10, 13, 363, 13, + 21, 5, 5, 9, 5, 21, 362, 5, 25, 5, 25, 5, 26, 25, 25, 25, 25, 5, 5, 7, - 10, 5, 27, 8, 28, 5, 44, 26, 31, 17, - 5, 17, 17, 17, 17, 352, 72, 5, 5, 15, - 15, 15, 17, 31, 15, 27, 19, 28, 19, 19, - 19, 19, 20, 20, 20, 20, 72, 351, 17, 19, - 32, 33, 15, 20, 37, 42, 37, 42, 45, 45, - 45, 350, 15, 45, 48, 19, 15, 15, 15, 20, - 15, 48, 15, 32, 33, 15, 15, 15, 15, 15, - 202, 15, 22, 15, 22, 22, 22, 22, 47, 47, - 47, 45, 48, 47, 74, 22, 48, 49, 49, 49, - - 48, 175, 49, 50, 50, 50, 73, 48, 50, 75, - 48, 22, 48, 48, 51, 51, 51, 74, 77, 51, - 82, 47, 52, 52, 52, 148, 73, 52, 51, 75, - 49, 76, 118, 49, 110, 108, 50, 47, 53, 53, - 53, 77, 109, 53, 54, 54, 54, 51, 82, 54, - 110, 76, 50, 111, 51, 52, 113, 51, 108, 55, - 55, 55, 109, 112, 55, 56, 56, 56, 52, 142, - 56, 53, 113, 57, 57, 57, 111, 54, 57, 58, - 58, 58, 114, 112, 58, 142, 86, 53, 54, 145, - 80, 53, 55, 54, 79, 55, 43, 41, 56, 39, - - 38, 56, 59, 59, 59, 145, 57, 59, 60, 60, - 60, 24, 58, 60, 14, 58, 11, 62, 62, 62, - 62, 63, 0, 63, 63, 63, 63, 57, 62, 0, - 0, 64, 0, 64, 63, 59, 64, 64, 64, 64, - 0, 60, 59, 0, 62, 0, 66, 66, 66, 66, - 63, 59, 70, 70, 70, 70, 60, 66, 0, 65, - 60, 65, 65, 65, 65, 71, 71, 71, 71, 84, - 0, 0, 65, 66, 0, 0, 84, 85, 85, 85, - 0, 0, 85, 0, 0, 0, 0, 0, 65, 87, - 87, 87, 0, 0, 87, 0, 0, 84, 90, 90, - - 90, 84, 0, 90, 0, 84, 89, 89, 89, 0, - 85, 89, 84, 0, 0, 84, 0, 84, 84, 0, - 0, 0, 87, 0, 0, 85, 88, 88, 88, 88, - 0, 90, 0, 0, 88, 88, 88, 88, 88, 89, - 0, 0, 91, 91, 91, 90, 90, 91, 0, 88, - 88, 88, 88, 88, 88, 92, 92, 92, 89, 0, - 92, 93, 93, 93, 0, 0, 93, 94, 94, 94, - 0, 0, 94, 0, 0, 91, 95, 95, 95, 0, - 0, 95, 96, 96, 96, 0, 0, 96, 92, 0, - 0, 0, 92, 0, 93, 0, 97, 97, 97, 93, - - 94, 97, 0, 98, 98, 98, 0, 0, 98, 95, - 0, 99, 99, 99, 0, 96, 99, 100, 100, 100, - 0, 94, 100, 0, 0, 95, 101, 101, 101, 97, - 0, 101, 0, 97, 0, 96, 98, 102, 102, 102, - 0, 0, 102, 0, 99, 98, 0, 103, 103, 103, - 100, 0, 103, 104, 104, 104, 0, 0, 104, 101, - 105, 105, 105, 0, 100, 105, 0, 0, 99, 0, - 102, 0, 106, 106, 106, 0, 0, 106, 0, 101, - 103, 0, 117, 117, 117, 0, 104, 117, 102, 102, - 102, 104, 0, 105, 0, 0, 121, 121, 121, 0, - - 0, 121, 103, 0, 105, 106, 0, 0, 122, 122, - 122, 0, 106, 122, 0, 117, 123, 123, 123, 0, - 0, 123, 0, 125, 125, 125, 0, 0, 125, 121, - 0, 0, 0, 0, 0, 117, 120, 120, 120, 120, - 121, 122, 0, 0, 120, 120, 120, 120, 120, 123, - 0, 0, 126, 126, 126, 122, 125, 126, 0, 120, - 120, 120, 120, 120, 120, 127, 127, 127, 0, 123, - 127, 128, 128, 128, 0, 0, 128, 125, 129, 129, - 129, 0, 0, 129, 0, 126, 130, 130, 130, 0, - 0, 130, 131, 131, 131, 0, 0, 131, 127, 0, - - 0, 0, 126, 0, 128, 132, 132, 132, 0, 0, - 132, 129, 0, 133, 133, 133, 128, 127, 133, 130, - 0, 134, 134, 134, 0, 131, 134, 0, 129, 0, - 135, 135, 135, 0, 131, 135, 0, 130, 132, 136, - 136, 136, 0, 0, 136, 0, 133, 137, 137, 137, - 0, 0, 137, 133, 134, 0, 0, 132, 0, 0, - 132, 0, 0, 135, 0, 0, 135, 0, 138, 138, - 138, 134, 136, 138, 139, 139, 139, 0, 0, 139, - 137, 140, 140, 140, 0, 0, 140, 0, 141, 141, - 141, 136, 0, 141, 150, 150, 150, 0, 0, 150, - - 137, 138, 0, 0, 152, 152, 152, 139, 138, 152, - 153, 153, 153, 0, 140, 153, 0, 0, 0, 139, - 0, 141, 0, 0, 0, 0, 0, 150, 154, 154, - 154, 0, 0, 154, 0, 0, 0, 152, 140, 141, - 0, 0, 152, 153, 0, 150, 151, 151, 151, 151, - 153, 0, 0, 0, 151, 151, 151, 151, 151, 0, - 0, 154, 155, 155, 155, 0, 0, 155, 0, 151, - 151, 151, 151, 151, 151, 156, 156, 156, 0, 154, - 156, 157, 157, 157, 0, 0, 157, 158, 158, 158, - 156, 156, 158, 0, 0, 155, 159, 159, 159, 0, - - 0, 159, 0, 0, 155, 0, 159, 0, 156, 0, - 160, 160, 160, 0, 157, 160, 161, 161, 161, 0, - 158, 161, 0, 0, 157, 162, 162, 162, 0, 159, - 162, 163, 163, 163, 0, 0, 163, 0, 0, 158, - 164, 164, 164, 160, 0, 164, 160, 0, 0, 161, - 165, 165, 165, 0, 0, 165, 161, 0, 162, 0, - 166, 166, 166, 0, 163, 166, 0, 0, 0, 162, - 0, 163, 0, 164, 0, 167, 167, 167, 0, 0, - 167, 0, 0, 165, 168, 168, 168, 0, 0, 168, - 169, 169, 169, 166, 0, 169, 170, 170, 170, 0, - - 0, 170, 0, 0, 165, 0, 0, 166, 167, 171, - 171, 171, 0, 0, 171, 0, 0, 168, 0, 0, - 172, 172, 172, 169, 168, 172, 0, 0, 0, 170, - 172, 167, 177, 177, 177, 0, 170, 177, 179, 179, - 179, 169, 171, 179, 183, 183, 183, 0, 179, 183, - 0, 0, 0, 172, 180, 180, 180, 0, 0, 180, - 0, 0, 181, 181, 181, 177, 0, 181, 182, 182, - 182, 179, 0, 182, 0, 0, 0, 183, 0, 0, - 0, 177, 178, 178, 178, 178, 0, 180, 0, 0, - 178, 178, 178, 178, 178, 181, 0, 0, 184, 184, - - 184, 182, 180, 184, 0, 178, 178, 178, 178, 178, - 178, 181, 0, 0, 182, 185, 185, 185, 0, 0, - 185, 0, 186, 186, 186, 0, 0, 186, 187, 187, - 187, 184, 186, 187, 188, 188, 188, 0, 0, 188, - 189, 189, 189, 0, 0, 189, 0, 0, 185, 190, - 190, 190, 0, 0, 190, 186, 0, 193, 193, 193, - 0, 187, 193, 191, 191, 191, 0, 188, 191, 0, - 0, 187, 0, 189, 0, 0, 0, 0, 187, 194, - 194, 194, 190, 0, 194, 188, 0, 195, 195, 195, - 193, 189, 195, 196, 196, 196, 191, 0, 196, 197, - - 197, 197, 0, 0, 197, 0, 0, 0, 190, 0, - 193, 0, 194, 0, 191, 0, 198, 198, 198, 194, - 195, 198, 201, 201, 201, 0, 196, 201, 204, 204, - 204, 0, 197, 204, 0, 0, 195, 205, 205, 205, - 0, 0, 205, 197, 196, 206, 206, 206, 0, 198, - 206, 207, 207, 207, 0, 201, 207, 0, 0, 0, - 201, 204, 208, 208, 208, 0, 0, 208, 0, 198, - 205, 0, 0, 205, 204, 212, 212, 212, 206, 0, - 212, 213, 213, 213, 207, 0, 213, 214, 214, 214, - 0, 0, 214, 0, 0, 208, 0, 207, 206, 215, - - 215, 215, 208, 0, 215, 0, 0, 0, 212, 0, - 216, 216, 216, 0, 213, 216, 0, 218, 218, 218, - 214, 212, 218, 217, 217, 217, 0, 0, 217, 0, - 213, 0, 215, 219, 219, 219, 214, 0, 219, 220, - 220, 220, 0, 216, 220, 0, 221, 221, 221, 0, - 218, 221, 0, 222, 222, 222, 217, 215, 222, 0, - 0, 0, 216, 217, 0, 0, 219, 0, 219, 223, - 223, 223, 220, 0, 223, 224, 224, 224, 0, 221, - 224, 0, 225, 225, 225, 224, 222, 225, 227, 227, - 227, 0, 220, 227, 228, 228, 228, 221, 227, 228, - - 0, 222, 223, 0, 229, 229, 229, 0, 224, 229, - 0, 231, 231, 231, 0, 225, 231, 0, 230, 230, - 230, 227, 223, 230, 232, 232, 232, 228, 230, 232, - 0, 225, 0, 0, 233, 233, 233, 229, 0, 233, - 234, 234, 234, 0, 231, 234, 0, 0, 228, 0, - 0, 230, 0, 0, 235, 235, 235, 232, 0, 235, - 236, 236, 236, 0, 0, 236, 231, 233, 232, 237, - 237, 237, 0, 234, 237, 240, 240, 240, 0, 0, - 240, 0, 0, 241, 241, 241, 233, 235, 241, 0, - 0, 234, 0, 236, 242, 242, 242, 0, 0, 242, - - 0, 0, 237, 0, 243, 243, 243, 0, 240, 243, - 244, 244, 244, 0, 0, 244, 241, 245, 245, 245, - 0, 0, 245, 241, 240, 0, 0, 242, 0, 246, - 246, 246, 0, 242, 246, 0, 0, 243, 0, 247, - 247, 247, 0, 244, 247, 0, 248, 248, 248, 0, - 245, 248, 250, 250, 250, 0, 0, 250, 251, 251, - 251, 0, 246, 251, 0, 245, 0, 0, 244, 0, - 245, 0, 247, 0, 0, 247, 0, 246, 0, 248, - 0, 252, 252, 252, 0, 250, 252, 253, 253, 253, - 0, 251, 253, 0, 0, 254, 254, 254, 251, 248, - - 254, 258, 258, 258, 250, 0, 258, 0, 259, 259, - 259, 0, 0, 259, 252, 0, 0, 0, 252, 0, - 253, 260, 260, 260, 0, 0, 260, 0, 254, 0, - 262, 262, 262, 0, 258, 262, 0, 263, 263, 263, - 253, 259, 263, 0, 264, 264, 264, 0, 254, 264, - 0, 258, 0, 0, 260, 265, 265, 265, 0, 259, - 265, 0, 0, 262, 266, 266, 266, 0, 0, 266, - 263, 0, 0, 263, 267, 267, 267, 264, 0, 267, - 268, 268, 268, 0, 0, 268, 0, 0, 265, 269, - 269, 269, 0, 0, 269, 0, 0, 266, 270, 270, - - 270, 0, 264, 270, 0, 0, 266, 267, 265, 271, - 271, 271, 0, 268, 271, 0, 0, 267, 272, 272, - 272, 0, 269, 272, 0, 273, 273, 273, 0, 268, - 273, 270, 274, 274, 274, 269, 0, 274, 277, 277, - 277, 0, 271, 277, 0, 0, 0, 0, 0, 270, - 0, 272, 0, 0, 278, 278, 278, 0, 273, 278, - 0, 279, 279, 279, 0, 274, 279, 280, 280, 280, - 0, 277, 280, 0, 0, 281, 281, 281, 273, 0, - 281, 282, 282, 282, 274, 277, 282, 278, 283, 283, - 283, 0, 0, 283, 279, 0, 0, 284, 284, 284, - - 280, 279, 284, 0, 278, 0, 0, 280, 281, 0, - 0, 287, 287, 287, 282, 281, 287, 0, 0, 282, - 0, 283, 0, 288, 288, 288, 0, 0, 288, 0, - 284, 0, 0, 284, 289, 289, 289, 0, 0, 289, - 290, 290, 290, 0, 287, 290, 291, 291, 291, 0, - 0, 291, 292, 292, 292, 287, 288, 292, 293, 293, - 293, 0, 0, 293, 294, 294, 294, 289, 0, 294, - 0, 0, 0, 290, 289, 0, 0, 0, 0, 291, - 290, 296, 296, 296, 0, 292, 296, 297, 297, 297, - 0, 293, 297, 299, 299, 299, 0, 294, 299, 0, - - 292, 0, 0, 291, 0, 0, 293, 0, 0, 294, - 300, 300, 300, 0, 296, 300, 301, 301, 301, 0, - 297, 301, 302, 302, 302, 0, 299, 302, 303, 303, - 303, 0, 296, 303, 0, 0, 297, 304, 304, 304, - 0, 0, 304, 300, 0, 305, 305, 305, 0, 301, - 305, 306, 306, 306, 0, 302, 306, 309, 309, 309, - 0, 303, 309, 310, 310, 310, 0, 0, 310, 301, - 304, 311, 311, 311, 0, 302, 311, 304, 305, 0, - 0, 303, 0, 0, 306, 0, 312, 312, 312, 305, - 309, 312, 313, 313, 313, 0, 310, 313, 0, 306, - - 314, 314, 314, 0, 311, 314, 0, 317, 317, 317, - 0, 0, 317, 0, 0, 311, 318, 318, 318, 312, - 0, 318, 319, 319, 319, 313, 0, 319, 0, 320, - 320, 320, 313, 314, 320, 0, 321, 321, 321, 312, - 317, 321, 322, 322, 322, 317, 0, 322, 0, 318, - 0, 0, 314, 0, 0, 319, 323, 323, 323, 0, - 0, 323, 320, 0, 0, 325, 325, 325, 318, 321, - 325, 0, 321, 0, 319, 322, 328, 328, 328, 0, - 0, 328, 329, 329, 329, 0, 0, 329, 0, 323, - 330, 330, 330, 0, 0, 330, 0, 0, 325, 0, - - 331, 331, 331, 0, 0, 331, 332, 332, 332, 328, - 331, 332, 333, 333, 333, 329, 0, 333, 325, 0, - 328, 0, 0, 330, 0, 334, 334, 334, 0, 0, - 334, 329, 0, 331, 0, 336, 336, 336, 330, 332, - 336, 337, 337, 337, 0, 333, 337, 0, 338, 338, - 338, 0, 331, 338, 0, 0, 0, 332, 334, 339, - 339, 339, 0, 0, 339, 334, 0, 0, 336, 0, - 0, 336, 0, 0, 337, 0, 0, 0, 0, 0, - 0, 338, 0, 0, 0, 0, 0, 337, 0, 0, - 0, 0, 339, 0, 0, 338, 342, 342, 342, 342, - - 342, 343, 343, 343, 343, 343, 344, 0, 344, 344, - 344, 345, 0, 345, 0, 345, 346, 346, 346, 346, - 346, 347, 347, 347, 347, 347, 348, 0, 348, 348, - 348, 349, 349, 349, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341, 341, 341, 341, - 341, 341, 341, 341, 341, 341, 341 - + 10, 5, 27, 8, 37, 5, 37, 26, 28, 17, + 5, 17, 17, 17, 17, 361, 32, 5, 5, 15, + 15, 15, 17, 33, 15, 27, 20, 20, 20, 20, + 19, 28, 19, 19, 19, 19, 31, 20, 17, 32, + 77, 75, 15, 19, 76, 42, 33, 42, 360, 221, + 190, 31, 15, 20, 44, 15, 15, 15, 15, 19, + 15, 75, 15, 77, 76, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 22, 78, 22, 22, 22, 22, + 85, 79, 44, 45, 45, 45, 159, 22, 45, 47, + + 47, 47, 125, 48, 47, 78, 121, 49, 49, 49, + 48, 79, 49, 22, 50, 50, 50, 117, 85, 50, + 51, 51, 51, 89, 83, 51, 45, 73, 73, 73, + 73, 48, 47, 117, 80, 48, 67, 115, 67, 48, + 49, 67, 67, 67, 67, 116, 48, 50, 47, 48, + 50, 48, 48, 51, 52, 52, 52, 80, 120, 52, + 115, 49, 53, 53, 53, 116, 51, 53, 52, 51, + 54, 54, 54, 118, 120, 54, 55, 55, 55, 82, + 43, 55, 74, 74, 74, 74, 153, 52, 56, 56, + 56, 41, 39, 56, 52, 53, 118, 52, 119, 57, + + 57, 57, 153, 54, 57, 58, 58, 58, 53, 55, + 58, 59, 59, 59, 38, 156, 59, 24, 119, 54, + 55, 56, 14, 54, 56, 55, 11, 0, 60, 60, + 60, 156, 57, 60, 0, 57, 0, 0, 58, 0, + 61, 61, 61, 0, 59, 61, 0, 59, 62, 62, + 62, 0, 0, 62, 0, 63, 63, 63, 0, 58, + 63, 60, 0, 65, 65, 65, 65, 0, 60, 0, + 0, 0, 0, 61, 65, 0, 0, 0, 0, 0, + 61, 62, 66, 0, 66, 66, 66, 66, 63, 61, + 65, 69, 69, 69, 69, 66, 68, 0, 68, 68, + + 68, 68, 69, 63, 0, 87, 62, 63, 0, 68, + 0, 66, 87, 0, 88, 88, 88, 0, 69, 88, + 0, 0, 90, 90, 90, 68, 0, 90, 0, 0, + 0, 0, 0, 87, 95, 95, 95, 87, 0, 95, + 0, 87, 0, 0, 92, 92, 92, 88, 87, 92, + 0, 87, 0, 87, 87, 90, 0, 0, 0, 0, + 0, 0, 88, 91, 91, 91, 91, 95, 0, 0, + 0, 91, 91, 91, 91, 91, 0, 92, 93, 93, + 93, 95, 95, 93, 0, 0, 91, 91, 91, 91, + 91, 91, 0, 94, 94, 94, 0, 92, 94, 96, + + 96, 96, 0, 0, 96, 97, 97, 97, 0, 0, + 97, 93, 98, 98, 98, 0, 0, 98, 99, 99, + 99, 0, 0, 99, 0, 0, 94, 0, 0, 0, + 93, 0, 96, 0, 100, 100, 100, 94, 97, 100, + 0, 0, 97, 0, 0, 98, 0, 101, 101, 101, + 98, 99, 101, 102, 102, 102, 0, 0, 102, 103, + 103, 103, 0, 0, 103, 0, 0, 100, 0, 104, + 104, 104, 99, 0, 104, 0, 105, 105, 105, 0, + 101, 105, 0, 100, 0, 0, 102, 0, 0, 0, + 102, 0, 103, 0, 106, 106, 106, 0, 0, 106, + + 101, 103, 104, 107, 107, 107, 0, 0, 107, 105, + 108, 108, 108, 0, 0, 108, 109, 109, 109, 0, + 0, 109, 0, 105, 0, 0, 104, 106, 110, 110, + 110, 0, 0, 110, 0, 0, 107, 111, 111, 111, + 0, 0, 111, 108, 0, 0, 108, 106, 0, 109, + 0, 0, 0, 0, 107, 107, 107, 112, 112, 112, + 0, 110, 112, 113, 113, 113, 110, 0, 113, 0, + 111, 109, 124, 124, 124, 0, 0, 124, 128, 128, + 128, 0, 0, 128, 130, 130, 130, 111, 0, 130, + 112, 0, 0, 0, 0, 0, 113, 129, 129, 129, + + 0, 112, 129, 113, 0, 124, 0, 134, 134, 134, + 0, 128, 134, 131, 131, 131, 0, 130, 131, 0, + 0, 128, 0, 0, 130, 124, 127, 127, 127, 127, + 129, 0, 0, 0, 127, 127, 127, 127, 127, 0, + 134, 129, 132, 132, 132, 0, 131, 132, 0, 127, + 127, 127, 127, 127, 127, 0, 0, 135, 135, 135, + 131, 134, 135, 136, 136, 136, 0, 0, 136, 137, + 137, 137, 0, 0, 137, 132, 138, 138, 138, 0, + 0, 138, 0, 139, 139, 139, 0, 0, 139, 0, + 135, 0, 141, 141, 141, 132, 136, 141, 140, 140, + + 140, 0, 137, 140, 0, 0, 0, 135, 0, 138, + 0, 0, 0, 0, 137, 136, 139, 142, 142, 142, + 0, 0, 142, 0, 0, 141, 138, 143, 143, 143, + 0, 140, 143, 0, 139, 0, 144, 144, 144, 0, + 140, 144, 0, 0, 141, 0, 0, 141, 0, 0, + 142, 145, 145, 145, 0, 0, 145, 142, 0, 0, + 143, 146, 146, 146, 0, 0, 146, 0, 0, 144, + 0, 0, 144, 147, 147, 147, 0, 143, 147, 0, + 148, 148, 148, 0, 145, 148, 0, 0, 149, 149, + 149, 0, 0, 149, 146, 150, 150, 150, 0, 0, + + 150, 0, 0, 145, 0, 0, 147, 151, 151, 151, + 0, 0, 151, 148, 146, 0, 0, 0, 0, 147, + 148, 149, 152, 152, 152, 0, 0, 152, 150, 161, + 161, 161, 0, 149, 161, 150, 163, 163, 163, 0, + 151, 163, 0, 0, 0, 0, 165, 165, 165, 0, + 0, 165, 173, 173, 173, 152, 0, 173, 0, 0, + 0, 0, 161, 0, 151, 164, 164, 164, 0, 163, + 164, 0, 0, 152, 0, 0, 163, 0, 0, 165, + 161, 162, 162, 162, 162, 173, 0, 0, 173, 162, + 162, 162, 162, 162, 165, 166, 166, 166, 164, 0, + + 166, 0, 0, 164, 162, 162, 162, 162, 162, 162, + 167, 167, 167, 0, 0, 167, 168, 168, 168, 0, + 0, 168, 169, 169, 169, 0, 0, 169, 166, 170, + 170, 170, 0, 0, 170, 166, 0, 169, 169, 0, + 171, 171, 171, 167, 0, 171, 172, 172, 172, 168, + 0, 172, 177, 177, 177, 169, 172, 177, 168, 0, + 0, 167, 170, 174, 174, 174, 0, 0, 174, 175, + 175, 175, 170, 171, 175, 176, 176, 176, 0, 172, + 176, 178, 178, 178, 0, 177, 178, 0, 0, 179, + 179, 179, 171, 0, 179, 0, 174, 0, 0, 180, + + 180, 180, 175, 174, 180, 181, 181, 181, 176, 0, + 181, 0, 0, 175, 178, 176, 182, 182, 182, 0, + 0, 182, 179, 183, 183, 183, 0, 0, 183, 184, + 184, 184, 180, 0, 184, 178, 179, 0, 181, 185, + 185, 185, 0, 0, 185, 181, 186, 186, 186, 182, + 0, 186, 192, 192, 192, 180, 183, 192, 0, 194, + 194, 194, 184, 182, 194, 187, 187, 187, 0, 184, + 187, 0, 185, 0, 183, 187, 195, 195, 195, 186, + 0, 195, 196, 196, 196, 192, 0, 196, 197, 197, + 197, 0, 194, 197, 0, 0, 0, 0, 187, 0, + + 0, 192, 193, 193, 193, 193, 0, 194, 0, 195, + 193, 193, 193, 193, 193, 196, 0, 198, 198, 198, + 0, 197, 198, 0, 0, 193, 193, 193, 193, 193, + 193, 0, 199, 199, 199, 196, 197, 199, 200, 200, + 200, 0, 0, 200, 201, 201, 201, 0, 0, 201, + 198, 202, 202, 202, 0, 0, 202, 203, 203, 203, + 0, 0, 203, 0, 0, 199, 198, 203, 204, 204, + 204, 200, 0, 204, 205, 205, 205, 201, 199, 205, + 206, 206, 206, 0, 202, 206, 207, 207, 207, 0, + 203, 207, 0, 208, 208, 208, 0, 0, 208, 0, + + 0, 204, 0, 210, 210, 210, 0, 205, 210, 0, + 0, 204, 0, 206, 0, 211, 211, 211, 204, 207, + 211, 0, 0, 0, 0, 205, 208, 212, 212, 212, + 0, 206, 212, 213, 213, 213, 210, 0, 213, 0, + 0, 214, 214, 214, 208, 207, 214, 0, 211, 215, + 215, 215, 0, 0, 215, 211, 210, 216, 216, 216, + 212, 0, 216, 220, 220, 220, 213, 0, 220, 0, + 223, 223, 223, 0, 214, 223, 212, 0, 224, 224, + 224, 0, 215, 224, 213, 0, 226, 226, 226, 0, + 216, 226, 0, 215, 0, 0, 220, 227, 227, 227, + + 0, 220, 227, 223, 0, 0, 0, 228, 228, 228, + 216, 224, 228, 233, 233, 233, 223, 0, 233, 226, + 0, 229, 229, 229, 0, 0, 229, 234, 234, 234, + 227, 224, 234, 0, 235, 235, 235, 0, 226, 235, + 228, 0, 236, 236, 236, 0, 233, 236, 0, 0, + 227, 0, 0, 228, 229, 0, 0, 0, 0, 233, + 234, 229, 0, 237, 237, 237, 0, 235, 237, 238, + 238, 238, 0, 0, 238, 236, 234, 239, 239, 239, + 0, 0, 239, 235, 240, 240, 240, 0, 0, 240, + 241, 241, 241, 0, 0, 241, 237, 0, 0, 0, + + 236, 0, 238, 242, 242, 242, 0, 0, 242, 238, + 239, 243, 243, 243, 0, 237, 243, 240, 0, 240, + 245, 245, 245, 241, 0, 245, 0, 246, 246, 246, + 0, 0, 246, 247, 247, 247, 242, 246, 247, 0, + 0, 0, 0, 241, 243, 249, 249, 249, 0, 0, + 249, 0, 0, 245, 242, 249, 250, 250, 250, 243, + 246, 250, 251, 251, 251, 0, 247, 251, 0, 252, + 252, 252, 0, 245, 252, 253, 253, 253, 249, 0, + 253, 0, 247, 0, 0, 253, 254, 254, 254, 250, + 0, 254, 255, 255, 255, 251, 0, 255, 0, 0, + + 250, 0, 252, 0, 256, 256, 256, 0, 253, 256, + 257, 257, 257, 0, 0, 257, 258, 258, 258, 254, + 0, 258, 259, 259, 259, 255, 0, 259, 0, 260, + 260, 260, 0, 0, 260, 0, 255, 256, 0, 0, + 0, 254, 0, 257, 0, 263, 263, 263, 0, 258, + 263, 0, 264, 264, 264, 259, 256, 264, 265, 265, + 265, 257, 260, 265, 0, 266, 266, 266, 0, 0, + 266, 267, 267, 267, 0, 0, 267, 0, 263, 268, + 268, 268, 0, 0, 268, 264, 0, 0, 269, 269, + 269, 265, 264, 269, 263, 0, 0, 265, 266, 0, + + 0, 270, 270, 270, 267, 0, 270, 0, 271, 271, + 271, 0, 268, 271, 274, 274, 274, 0, 0, 274, + 0, 269, 0, 275, 275, 275, 0, 268, 275, 267, + 0, 0, 268, 0, 270, 0, 269, 270, 276, 276, + 276, 271, 0, 276, 0, 0, 271, 274, 277, 277, + 277, 0, 0, 277, 0, 0, 275, 278, 278, 278, + 0, 0, 278, 275, 0, 0, 274, 282, 282, 282, + 0, 276, 282, 0, 0, 276, 0, 0, 283, 283, + 283, 277, 0, 283, 0, 0, 284, 284, 284, 0, + 278, 284, 286, 286, 286, 0, 0, 286, 0, 0, + + 282, 277, 287, 287, 287, 0, 0, 287, 0, 0, + 278, 283, 0, 288, 288, 288, 0, 282, 288, 284, + 0, 289, 289, 289, 0, 286, 289, 0, 0, 283, + 0, 290, 290, 290, 0, 287, 290, 0, 287, 291, + 291, 291, 0, 0, 291, 0, 288, 292, 292, 292, + 0, 0, 292, 0, 289, 293, 293, 293, 0, 0, + 293, 294, 294, 294, 290, 0, 294, 0, 0, 0, + 0, 288, 291, 290, 289, 291, 295, 295, 295, 0, + 292, 295, 296, 296, 296, 0, 0, 296, 293, 0, + 297, 297, 297, 0, 294, 297, 292, 298, 298, 298, + + 0, 293, 298, 301, 301, 301, 0, 0, 301, 295, + 0, 0, 294, 0, 0, 296, 0, 0, 0, 302, + 302, 302, 0, 297, 302, 0, 303, 303, 303, 0, + 298, 303, 304, 304, 304, 0, 301, 304, 0, 0, + 305, 305, 305, 297, 0, 305, 306, 306, 306, 298, + 301, 306, 302, 307, 307, 307, 0, 0, 307, 303, + 0, 0, 308, 308, 308, 304, 303, 308, 0, 302, + 0, 0, 304, 305, 0, 311, 311, 311, 0, 306, + 311, 0, 0, 0, 306, 0, 307, 312, 312, 312, + 0, 0, 312, 305, 0, 308, 0, 0, 308, 313, + + 313, 313, 0, 0, 313, 314, 314, 314, 311, 0, + 314, 315, 315, 315, 0, 0, 315, 0, 0, 311, + 312, 316, 316, 316, 0, 0, 316, 0, 317, 317, + 317, 0, 313, 317, 0, 0, 0, 0, 314, 313, + 0, 318, 318, 318, 315, 314, 318, 320, 320, 320, + 0, 0, 320, 0, 316, 321, 321, 321, 0, 0, + 321, 317, 323, 323, 323, 0, 0, 323, 315, 316, + 0, 0, 317, 0, 318, 0, 324, 324, 324, 0, + 320, 324, 325, 325, 325, 0, 318, 325, 321, 326, + 326, 326, 0, 0, 326, 323, 0, 0, 320, 0, + + 327, 327, 327, 0, 321, 327, 328, 328, 328, 324, + 0, 328, 329, 329, 329, 325, 0, 329, 330, 330, + 330, 0, 326, 330, 333, 333, 333, 0, 0, 333, + 0, 0, 0, 327, 0, 325, 334, 334, 334, 328, + 0, 334, 326, 0, 0, 329, 328, 0, 0, 327, + 0, 330, 0, 335, 335, 335, 329, 333, 335, 336, + 336, 336, 0, 0, 336, 0, 330, 0, 0, 334, + 337, 337, 337, 0, 0, 337, 338, 338, 338, 0, + 0, 338, 341, 341, 341, 0, 335, 341, 342, 342, + 342, 0, 336, 342, 343, 343, 343, 0, 0, 343, + + 0, 335, 0, 337, 0, 0, 344, 344, 344, 338, + 337, 344, 336, 0, 0, 341, 0, 346, 346, 346, + 0, 342, 346, 0, 347, 347, 347, 343, 338, 347, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 344, + 342, 0, 0, 0, 0, 0, 343, 0, 0, 0, + 346, 0, 0, 0, 0, 0, 0, 347, 352, 352, + 352, 352, 352, 353, 353, 353, 353, 353, 354, 0, + 354, 354, 354, 355, 0, 355, 0, 355, 356, 356, + 356, 356, 356, 357, 357, 357, 357, 357, 358, 0, + 358, 358, 358, 359, 359, 359, 351, 351, 351, 351, + + 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, + 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, + 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, + 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, + 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, + 351, 351, 351, 351, 351, 351, 351, 351, 351 } ; static yy_state_type yy_last_accepting_state; @@ -1391,14 +1406,15 @@ static char *yy_last_accepting_cpos; extern int yy_flex_debug; int yy_flex_debug = 1; -static const flex_int16_t yy_rule_linenum[59] = +static const flex_int16_t yy_rule_linenum[62] = { 0, 133, 135, 137, 142, 143, 148, 149, 150, 162, 165, - 170, 177, 186, 195, 204, 213, 225, 237, 246, 255, + 170, 177, 186, 195, 204, 216, 228, 237, 246, 255, 264, 273, 282, 291, 300, 309, 318, 327, 336, 345, 354, 363, 372, 381, 390, 399, 408, 417, 426, 435, - 444, 543, 548, 553, 558, 559, 560, 561, 562, 563, - 565, 583, 596, 601, 605, 607, 609, 611 + 444, 453, 462, 471, 570, 575, 580, 585, 586, 587, + 588, 589, 590, 592, 610, 623, 628, 632, 634, 636, + 638 } ; /* The intent behind this definition is that it'll catch @@ -1453,7 +1469,7 @@ using isc::agent::AgentParser; /* To avoid the call to exit... oops! */ #define YY_FATAL_ERROR(msg) isc::agent::ParserContext::fatal(msg) -#line 1456 "agent_lexer.cc" +#line 1472 "agent_lexer.cc" /* noyywrap disables automatic rewinding for the next file to parse. Since we always parse only a single string, there's no need to do any wraps. And using yywrap requires linking with -lfl, which provides the default yywrap @@ -1479,8 +1495,8 @@ using isc::agent::AgentParser; by moving it ahead by yyleng bytes. yyleng specifies the length of the currently matched token. */ #define YY_USER_ACTION driver.loc_.columns(yyleng); -#line 1482 "agent_lexer.cc" -#line 1483 "agent_lexer.cc" +#line 1498 "agent_lexer.cc" +#line 1499 "agent_lexer.cc" #define INITIAL 0 #define COMMENT 1 @@ -1794,7 +1810,7 @@ YY_DECL } -#line 1797 "agent_lexer.cc" +#line 1813 "agent_lexer.cc" while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */ { @@ -1823,13 +1839,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 342 ) + if ( yy_current_state >= 352 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; ++yy_cp; } - while ( yy_current_state != 341 ); + while ( yy_current_state != 351 ); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); @@ -1848,13 +1864,13 @@ do_action: /* This label is used only to access EOF actions. */ { if ( yy_act == 0 ) fprintf( stderr, "--scanner backing up\n" ); - else if ( yy_act < 59 ) + else if ( yy_act < 62 ) fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n", (long)yy_rule_linenum[yy_act], yytext ); - else if ( yy_act == 59 ) + else if ( yy_act == 62 ) fprintf( stderr, "--accepting default rule (\"%s\")\n", yytext ); - else if ( yy_act == 60 ) + else if ( yy_act == 63 ) fprintf( stderr, "--(end of buffer or a NUL)\n" ); else fprintf( stderr, "--EOF (start condition %d)\n", YY_START ); @@ -2000,39 +2016,39 @@ YY_RULE_SETUP { switch(driver.ctx_) { case ParserContext::AGENT: - return AgentParser::make_BASIC_AUTHENTICATION_REALM(driver.loc_); + case ParserContext::SERVER: + case ParserContext::LOGGERS: + case ParserContext::CLIENTS: + return AgentParser::make_USER_CONTEXT(driver.loc_); default: - return AgentParser::make_STRING("basic-authentication-realm", driver.loc_); + return AgentParser::make_STRING("user-context", driver.loc_); } } YY_BREAK case 16: YY_RULE_SETUP -#line 213 "agent_lexer.ll" +#line 216 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::AGENT: case ParserContext::SERVER: case ParserContext::LOGGERS: - case ParserContext::BASIC_AUTHENTICATIONS: - return AgentParser::make_USER_CONTEXT(driver.loc_); + case ParserContext::CLIENTS: + return AgentParser::make_COMMENT(driver.loc_); default: - return AgentParser::make_STRING("user-context", driver.loc_); + return AgentParser::make_STRING("comment", driver.loc_); } } YY_BREAK case 17: YY_RULE_SETUP -#line 225 "agent_lexer.ll" +#line 228 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::AGENT: - case ParserContext::SERVER: - case ParserContext::LOGGERS: - case ParserContext::BASIC_AUTHENTICATIONS: - return AgentParser::make_COMMENT(driver.loc_); + return AgentParser::make_AUTHENTICATION(driver.loc_); default: - return AgentParser::make_STRING("comment", driver.loc_); + return AgentParser::make_STRING("authentication", driver.loc_); } } YY_BREAK @@ -2041,10 +2057,10 @@ YY_RULE_SETUP #line 237 "agent_lexer.ll" { switch(driver.ctx_) { - case ParserContext::AGENT: - return AgentParser::make_CONTROL_SOCKETS(driver.loc_); + case ParserContext::AUTHENTICATION: + return AgentParser::make_TYPE(driver.loc_); default: - return AgentParser::make_STRING("control-sockets", driver.loc_); + return AgentParser::make_STRING("type", driver.loc_); } } YY_BREAK @@ -2053,10 +2069,10 @@ YY_RULE_SETUP #line 246 "agent_lexer.ll" { switch(driver.ctx_) { - case ParserContext::CONTROL_SOCKETS: - return AgentParser::make_DHCP4_SERVER(driver.loc_); + case ParserContext::AUTH_TYPE: + return AgentParser::make_BASIC(driver.loc_); default: - return AgentParser::make_STRING("dhcp4", driver.loc_); + return AgentParser::make_STRING("basic", driver.loc_); } } YY_BREAK @@ -2065,10 +2081,10 @@ YY_RULE_SETUP #line 255 "agent_lexer.ll" { switch(driver.ctx_) { - case ParserContext::CONTROL_SOCKETS: - return AgentParser::make_DHCP6_SERVER(driver.loc_); + case ParserContext::AUTHENTICATION: + return AgentParser::make_REALM(driver.loc_); default: - return AgentParser::make_STRING("dhcp6", driver.loc_); + return AgentParser::make_STRING("authentication", driver.loc_); } } YY_BREAK @@ -2077,10 +2093,10 @@ YY_RULE_SETUP #line 264 "agent_lexer.ll" { switch(driver.ctx_) { - case ParserContext::CONTROL_SOCKETS: - return AgentParser::make_D2_SERVER(driver.loc_); + case ParserContext::AUTHENTICATION: + return AgentParser::make_CLIENTS(driver.loc_); default: - return AgentParser::make_STRING("d2", driver.loc_); + return AgentParser::make_STRING("clients", driver.loc_); } } YY_BREAK @@ -2089,10 +2105,10 @@ YY_RULE_SETUP #line 273 "agent_lexer.ll" { switch(driver.ctx_) { - case ParserContext::SERVER: - return AgentParser::make_SOCKET_NAME(driver.loc_); + case ParserContext::CLIENTS: + return AgentParser::make_USER(driver.loc_); default: - return AgentParser::make_STRING("socket-name", driver.loc_); + return AgentParser::make_STRING("user", driver.loc_); } } YY_BREAK @@ -2101,10 +2117,10 @@ YY_RULE_SETUP #line 282 "agent_lexer.ll" { switch(driver.ctx_) { - case ParserContext::SERVER: - return AgentParser::make_SOCKET_TYPE(driver.loc_); + case ParserContext::CLIENTS: + return AgentParser::make_PASSWORD(driver.loc_); default: - return AgentParser::make_STRING("socket-type", driver.loc_); + return AgentParser::make_STRING("password", driver.loc_); } } YY_BREAK @@ -2113,10 +2129,10 @@ YY_RULE_SETUP #line 291 "agent_lexer.ll" { switch(driver.ctx_) { - case ParserContext::SOCKET_TYPE: - return AgentParser::make_UNIX(driver.loc_); + case ParserContext::AGENT: + return AgentParser::make_CONTROL_SOCKETS(driver.loc_); default: - return AgentParser::make_STRING("unix", driver.loc_); + return AgentParser::make_STRING("control-sockets", driver.loc_); } } YY_BREAK @@ -2125,10 +2141,10 @@ YY_RULE_SETUP #line 300 "agent_lexer.ll" { switch(driver.ctx_) { - case ParserContext::AGENT: - return AgentParser::make_HOOKS_LIBRARIES(driver.loc_); + case ParserContext::CONTROL_SOCKETS: + return AgentParser::make_DHCP4_SERVER(driver.loc_); default: - return AgentParser::make_STRING("hooks-libraries", driver.loc_); + return AgentParser::make_STRING("dhcp4", driver.loc_); } } YY_BREAK @@ -2137,10 +2153,10 @@ YY_RULE_SETUP #line 309 "agent_lexer.ll" { switch(driver.ctx_) { - case ParserContext::HOOKS_LIBRARIES: - return AgentParser::make_LIBRARY(driver.loc_); + case ParserContext::CONTROL_SOCKETS: + return AgentParser::make_DHCP6_SERVER(driver.loc_); default: - return AgentParser::make_STRING("library", driver.loc_); + return AgentParser::make_STRING("dhcp6", driver.loc_); } } YY_BREAK @@ -2149,10 +2165,10 @@ YY_RULE_SETUP #line 318 "agent_lexer.ll" { switch(driver.ctx_) { - case ParserContext::HOOKS_LIBRARIES: - return AgentParser::make_PARAMETERS(driver.loc_); + case ParserContext::CONTROL_SOCKETS: + return AgentParser::make_D2_SERVER(driver.loc_); default: - return AgentParser::make_STRING("parameters", driver.loc_); + return AgentParser::make_STRING("d2", driver.loc_); } } YY_BREAK @@ -2161,10 +2177,10 @@ YY_RULE_SETUP #line 327 "agent_lexer.ll" { switch(driver.ctx_) { - case ParserContext::AGENT: - return AgentParser::make_LOGGERS(driver.loc_); + case ParserContext::SERVER: + return AgentParser::make_SOCKET_NAME(driver.loc_); default: - return AgentParser::make_STRING("loggers", driver.loc_); + return AgentParser::make_STRING("socket-name", driver.loc_); } } YY_BREAK @@ -2173,10 +2189,10 @@ YY_RULE_SETUP #line 336 "agent_lexer.ll" { switch(driver.ctx_) { - case ParserContext::LOGGERS: - return AgentParser::make_NAME(driver.loc_); + case ParserContext::SERVER: + return AgentParser::make_SOCKET_TYPE(driver.loc_); default: - return AgentParser::make_STRING("name", driver.loc_); + return AgentParser::make_STRING("socket-type", driver.loc_); } } YY_BREAK @@ -2185,10 +2201,10 @@ YY_RULE_SETUP #line 345 "agent_lexer.ll" { switch(driver.ctx_) { - case ParserContext::LOGGERS: - return AgentParser::make_OUTPUT_OPTIONS(driver.loc_); + case ParserContext::SOCKET_TYPE: + return AgentParser::make_UNIX(driver.loc_); default: - return AgentParser::make_STRING("output_options", driver.loc_); + return AgentParser::make_STRING("unix", driver.loc_); } } YY_BREAK @@ -2197,10 +2213,10 @@ YY_RULE_SETUP #line 354 "agent_lexer.ll" { switch(driver.ctx_) { - case ParserContext::OUTPUT_OPTIONS: - return AgentParser::make_OUTPUT(driver.loc_); + case ParserContext::AGENT: + return AgentParser::make_HOOKS_LIBRARIES(driver.loc_); default: - return AgentParser::make_STRING("output", driver.loc_); + return AgentParser::make_STRING("hooks-libraries", driver.loc_); } } YY_BREAK @@ -2209,10 +2225,10 @@ YY_RULE_SETUP #line 363 "agent_lexer.ll" { switch(driver.ctx_) { - case ParserContext::OUTPUT_OPTIONS: - return AgentParser::make_FLUSH(driver.loc_); + case ParserContext::HOOKS_LIBRARIES: + return AgentParser::make_LIBRARY(driver.loc_); default: - return AgentParser::make_STRING("flush", driver.loc_); + return AgentParser::make_STRING("library", driver.loc_); } } YY_BREAK @@ -2221,10 +2237,10 @@ YY_RULE_SETUP #line 372 "agent_lexer.ll" { switch(driver.ctx_) { - case ParserContext::OUTPUT_OPTIONS: - return AgentParser::make_MAXSIZE(driver.loc_); + case ParserContext::HOOKS_LIBRARIES: + return AgentParser::make_PARAMETERS(driver.loc_); default: - return AgentParser::make_STRING("maxsize", driver.loc_); + return AgentParser::make_STRING("parameters", driver.loc_); } } YY_BREAK @@ -2233,10 +2249,10 @@ YY_RULE_SETUP #line 381 "agent_lexer.ll" { switch(driver.ctx_) { - case ParserContext::OUTPUT_OPTIONS: - return AgentParser::make_MAXVER(driver.loc_); + case ParserContext::AGENT: + return AgentParser::make_LOGGERS(driver.loc_); default: - return AgentParser::make_STRING("maxver", driver.loc_); + return AgentParser::make_STRING("loggers", driver.loc_); } } YY_BREAK @@ -2245,10 +2261,10 @@ YY_RULE_SETUP #line 390 "agent_lexer.ll" { switch(driver.ctx_) { - case ParserContext::OUTPUT_OPTIONS: - return AgentParser::make_PATTERN(driver.loc_); + case ParserContext::LOGGERS: + return AgentParser::make_NAME(driver.loc_); default: - return AgentParser::make_STRING("pattern", driver.loc_); + return AgentParser::make_STRING("name", driver.loc_); } } YY_BREAK @@ -2258,9 +2274,9 @@ YY_RULE_SETUP { switch(driver.ctx_) { case ParserContext::LOGGERS: - return AgentParser::make_DEBUGLEVEL(driver.loc_); + return AgentParser::make_OUTPUT_OPTIONS(driver.loc_); default: - return AgentParser::make_STRING("debuglevel", driver.loc_); + return AgentParser::make_STRING("output_options", driver.loc_); } } YY_BREAK @@ -2269,10 +2285,10 @@ YY_RULE_SETUP #line 408 "agent_lexer.ll" { switch(driver.ctx_) { - case ParserContext::LOGGERS: - return AgentParser::make_SEVERITY(driver.loc_); + case ParserContext::OUTPUT_OPTIONS: + return AgentParser::make_OUTPUT(driver.loc_); default: - return AgentParser::make_STRING("severity", driver.loc_); + return AgentParser::make_STRING("output", driver.loc_); } } YY_BREAK @@ -2281,10 +2297,10 @@ YY_RULE_SETUP #line 417 "agent_lexer.ll" { switch(driver.ctx_) { - case ParserContext::AGENT: - return AgentParser::make_BASIC_AUTHENTICATIONS(driver.loc_); + case ParserContext::OUTPUT_OPTIONS: + return AgentParser::make_FLUSH(driver.loc_); default: - return AgentParser::make_STRING("basic-authentications", driver.loc_); + return AgentParser::make_STRING("flush", driver.loc_); } } YY_BREAK @@ -2293,10 +2309,10 @@ YY_RULE_SETUP #line 426 "agent_lexer.ll" { switch(driver.ctx_) { - case ParserContext::BASIC_AUTHENTICATIONS: - return AgentParser::make_USER(driver.loc_); + case ParserContext::OUTPUT_OPTIONS: + return AgentParser::make_MAXSIZE(driver.loc_); default: - return AgentParser::make_STRING("user", driver.loc_); + return AgentParser::make_STRING("maxsize", driver.loc_); } } YY_BREAK @@ -2305,16 +2321,52 @@ YY_RULE_SETUP #line 435 "agent_lexer.ll" { switch(driver.ctx_) { - case ParserContext::BASIC_AUTHENTICATIONS: - return AgentParser::make_PASSWORD(driver.loc_); + case ParserContext::OUTPUT_OPTIONS: + return AgentParser::make_MAXVER(driver.loc_); default: - return AgentParser::make_STRING("password", driver.loc_); + return AgentParser::make_STRING("maxver", driver.loc_); } } YY_BREAK case 41: YY_RULE_SETUP #line 444 "agent_lexer.ll" +{ + switch(driver.ctx_) { + case ParserContext::OUTPUT_OPTIONS: + return AgentParser::make_PATTERN(driver.loc_); + default: + return AgentParser::make_STRING("pattern", driver.loc_); + } +} + YY_BREAK +case 42: +YY_RULE_SETUP +#line 453 "agent_lexer.ll" +{ + switch(driver.ctx_) { + case ParserContext::LOGGERS: + return AgentParser::make_DEBUGLEVEL(driver.loc_); + default: + return AgentParser::make_STRING("debuglevel", driver.loc_); + } +} + YY_BREAK +case 43: +YY_RULE_SETUP +#line 462 "agent_lexer.ll" +{ + switch(driver.ctx_) { + case ParserContext::LOGGERS: + return AgentParser::make_SEVERITY(driver.loc_); + default: + return AgentParser::make_STRING("severity", driver.loc_); + } +} + YY_BREAK +case 44: +YY_RULE_SETUP +#line 471 "agent_lexer.ll" { /* A string has been matched. It contains the actual string and single quotes. We need to get those quotes out of the way and just use its content, e.g. @@ -2414,65 +2466,65 @@ YY_RULE_SETUP return AgentParser::make_STRING(decoded, driver.loc_); } YY_BREAK -case 42: -/* rule 42 can match eol */ +case 45: +/* rule 45 can match eol */ YY_RULE_SETUP -#line 543 "agent_lexer.ll" +#line 570 "agent_lexer.ll" { /* Bad string with a forbidden control character inside */ driver.error(driver.loc_, "Invalid control in " + std::string(yytext)); } YY_BREAK -case 43: -/* rule 43 can match eol */ +case 46: +/* rule 46 can match eol */ YY_RULE_SETUP -#line 548 "agent_lexer.ll" +#line 575 "agent_lexer.ll" { /* Bad string with a bad escape inside */ driver.error(driver.loc_, "Bad escape in " + std::string(yytext)); } YY_BREAK -case 44: +case 47: YY_RULE_SETUP -#line 553 "agent_lexer.ll" +#line 580 "agent_lexer.ll" { /* Bad string with an open escape at the end */ driver.error(driver.loc_, "Overflow escape in " + std::string(yytext)); } YY_BREAK -case 45: +case 48: YY_RULE_SETUP -#line 558 "agent_lexer.ll" +#line 585 "agent_lexer.ll" { return AgentParser::make_LSQUARE_BRACKET(driver.loc_); } YY_BREAK -case 46: +case 49: YY_RULE_SETUP -#line 559 "agent_lexer.ll" +#line 586 "agent_lexer.ll" { return AgentParser::make_RSQUARE_BRACKET(driver.loc_); } YY_BREAK -case 47: +case 50: YY_RULE_SETUP -#line 560 "agent_lexer.ll" +#line 587 "agent_lexer.ll" { return AgentParser::make_LCURLY_BRACKET(driver.loc_); } YY_BREAK -case 48: +case 51: YY_RULE_SETUP -#line 561 "agent_lexer.ll" +#line 588 "agent_lexer.ll" { return AgentParser::make_RCURLY_BRACKET(driver.loc_); } YY_BREAK -case 49: +case 52: YY_RULE_SETUP -#line 562 "agent_lexer.ll" +#line 589 "agent_lexer.ll" { return AgentParser::make_COMMA(driver.loc_); } YY_BREAK -case 50: +case 53: YY_RULE_SETUP -#line 563 "agent_lexer.ll" +#line 590 "agent_lexer.ll" { return AgentParser::make_COLON(driver.loc_); } YY_BREAK -case 51: +case 54: YY_RULE_SETUP -#line 565 "agent_lexer.ll" +#line 592 "agent_lexer.ll" { /* An integer was found. */ std::string tmp(yytext); @@ -2491,9 +2543,9 @@ YY_RULE_SETUP return AgentParser::make_INTEGER(integer, driver.loc_); } YY_BREAK -case 52: +case 55: YY_RULE_SETUP -#line 583 "agent_lexer.ll" +#line 610 "agent_lexer.ll" { /* A floating point was found. */ std::string tmp(yytext); @@ -2507,43 +2559,43 @@ YY_RULE_SETUP return AgentParser::make_FLOAT(fp, driver.loc_); } YY_BREAK -case 53: +case 56: YY_RULE_SETUP -#line 596 "agent_lexer.ll" +#line 623 "agent_lexer.ll" { string tmp(yytext); return AgentParser::make_BOOLEAN(tmp == "true", driver.loc_); } YY_BREAK -case 54: +case 57: YY_RULE_SETUP -#line 601 "agent_lexer.ll" +#line 628 "agent_lexer.ll" { return AgentParser::make_NULL_TYPE(driver.loc_); } YY_BREAK -case 55: +case 58: YY_RULE_SETUP -#line 605 "agent_lexer.ll" +#line 632 "agent_lexer.ll" driver.error (driver.loc_, "JSON true reserved keyword is lower case only"); YY_BREAK -case 56: +case 59: YY_RULE_SETUP -#line 607 "agent_lexer.ll" +#line 634 "agent_lexer.ll" driver.error (driver.loc_, "JSON false reserved keyword is lower case only"); YY_BREAK -case 57: +case 60: YY_RULE_SETUP -#line 609 "agent_lexer.ll" +#line 636 "agent_lexer.ll" driver.error (driver.loc_, "JSON null reserved keyword is lower case only"); YY_BREAK -case 58: +case 61: YY_RULE_SETUP -#line 611 "agent_lexer.ll" +#line 638 "agent_lexer.ll" driver.error (driver.loc_, "Invalid character: " + std::string(yytext)); YY_BREAK case YY_STATE_EOF(INITIAL): -#line 613 "agent_lexer.ll" +#line 640 "agent_lexer.ll" { if (driver.states_.empty()) { return AgentParser::make_END(driver.loc_); @@ -2567,12 +2619,12 @@ case YY_STATE_EOF(INITIAL): BEGIN(DIR_EXIT); } YY_BREAK -case 59: +case 62: YY_RULE_SETUP -#line 636 "agent_lexer.ll" +#line 663 "agent_lexer.ll" ECHO; YY_BREAK -#line 2575 "agent_lexer.cc" +#line 2627 "agent_lexer.cc" case YY_END_OF_BUFFER: { @@ -2891,7 +2943,7 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 342 ) + if ( yy_current_state >= 352 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; @@ -2924,11 +2976,11 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 342 ) + if ( yy_current_state >= 352 ) yy_c = yy_meta[yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c]; - yy_is_jam = (yy_current_state == 341); + yy_is_jam = (yy_current_state == 351); return yy_is_jam ? 0 : yy_current_state; } @@ -3677,7 +3729,7 @@ void yyfree (void * ptr ) /* %ok-for-header */ -#line 636 "agent_lexer.ll" +#line 663 "agent_lexer.ll" using namespace isc::dhcp; diff --git a/src/bin/agent/agent_parser.cc b/src/bin/agent/agent_parser.cc index 44a2f86c7a..afc2020689 100644 --- a/src/bin/agent/agent_parser.cc +++ b/src/bin/agent/agent_parser.cc @@ -212,6 +212,7 @@ namespace isc { namespace agent { case symbol_kind::S_value: // value case symbol_kind::S_map_value: // map_value case symbol_kind::S_socket_type_value: // socket_type_value + case symbol_kind::S_auth_type_value: // auth_type_value value.YY_MOVE_OR_COPY< ElementPtr > (YY_MOVE (that.value)); break; @@ -249,6 +250,7 @@ namespace isc { namespace agent { case symbol_kind::S_value: // value case symbol_kind::S_map_value: // map_value case symbol_kind::S_socket_type_value: // socket_type_value + case symbol_kind::S_auth_type_value: // auth_type_value value.move< ElementPtr > (YY_MOVE (that.value)); break; @@ -286,6 +288,7 @@ namespace isc { namespace agent { case symbol_kind::S_value: // value case symbol_kind::S_map_value: // map_value case symbol_kind::S_socket_type_value: // socket_type_value + case symbol_kind::S_auth_type_value: // auth_type_value value.copy< ElementPtr > (that.value); break; @@ -322,6 +325,7 @@ namespace isc { namespace agent { case symbol_kind::S_value: // value case symbol_kind::S_map_value: // map_value case symbol_kind::S_socket_type_value: // socket_type_value + case symbol_kind::S_auth_type_value: // auth_type_value value.move< ElementPtr > (that.value); break; @@ -378,45 +382,51 @@ namespace isc { namespace agent { switch (yykind) { case symbol_kind::S_STRING: // "constant string" -#line 104 "agent_parser.yy" +#line 108 "agent_parser.yy" { yyoutput << yysym.value.template as < std::string > (); } -#line 384 "agent_parser.cc" +#line 388 "agent_parser.cc" break; case symbol_kind::S_INTEGER: // "integer" -#line 104 "agent_parser.yy" +#line 108 "agent_parser.yy" { yyoutput << yysym.value.template as < int64_t > (); } -#line 390 "agent_parser.cc" +#line 394 "agent_parser.cc" break; case symbol_kind::S_FLOAT: // "floating point" -#line 104 "agent_parser.yy" +#line 108 "agent_parser.yy" { yyoutput << yysym.value.template as < double > (); } -#line 396 "agent_parser.cc" +#line 400 "agent_parser.cc" break; case symbol_kind::S_BOOLEAN: // "boolean" -#line 104 "agent_parser.yy" +#line 108 "agent_parser.yy" { yyoutput << yysym.value.template as < bool > (); } -#line 402 "agent_parser.cc" +#line 406 "agent_parser.cc" break; case symbol_kind::S_value: // value -#line 104 "agent_parser.yy" +#line 108 "agent_parser.yy" { yyoutput << yysym.value.template as < ElementPtr > (); } -#line 408 "agent_parser.cc" +#line 412 "agent_parser.cc" break; case symbol_kind::S_map_value: // map_value -#line 104 "agent_parser.yy" +#line 108 "agent_parser.yy" { yyoutput << yysym.value.template as < ElementPtr > (); } -#line 414 "agent_parser.cc" +#line 418 "agent_parser.cc" break; case symbol_kind::S_socket_type_value: // socket_type_value -#line 104 "agent_parser.yy" +#line 108 "agent_parser.yy" { yyoutput << yysym.value.template as < ElementPtr > (); } -#line 420 "agent_parser.cc" +#line 424 "agent_parser.cc" + break; + + case symbol_kind::S_auth_type_value: // auth_type_value +#line 108 "agent_parser.yy" + { yyoutput << yysym.value.template as < ElementPtr > (); } +#line 430 "agent_parser.cc" break; default: @@ -649,6 +659,7 @@ namespace isc { namespace agent { case symbol_kind::S_value: // value case symbol_kind::S_map_value: // map_value case symbol_kind::S_socket_type_value: // socket_type_value + case symbol_kind::S_auth_type_value: // auth_type_value yylhs.value.emplace< ElementPtr > (); break; @@ -689,206 +700,206 @@ namespace isc { namespace agent { switch (yyn) { case 2: // $@1: %empty -#line 115 "agent_parser.yy" +#line 119 "agent_parser.yy" { ctx.ctx_ = ctx.NO_KEYWORDS; } -#line 695 "agent_parser.cc" +#line 706 "agent_parser.cc" break; case 4: // $@2: %empty -#line 116 "agent_parser.yy" +#line 120 "agent_parser.yy" { ctx.ctx_ = ctx.CONFIG; } -#line 701 "agent_parser.cc" +#line 712 "agent_parser.cc" break; case 6: // $@3: %empty -#line 117 "agent_parser.yy" +#line 121 "agent_parser.yy" { ctx.ctx_ = ctx.AGENT; } -#line 707 "agent_parser.cc" +#line 718 "agent_parser.cc" break; case 8: // $@4: %empty -#line 125 "agent_parser.yy" +#line 129 "agent_parser.yy" { // Parse the Control-agent map ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.push_back(m); } -#line 717 "agent_parser.cc" +#line 728 "agent_parser.cc" break; case 9: // sub_agent: "{" $@4 global_params "}" -#line 129 "agent_parser.yy" +#line 133 "agent_parser.yy" { // parsing completed } -#line 725 "agent_parser.cc" +#line 736 "agent_parser.cc" break; case 10: // json: value -#line 136 "agent_parser.yy" +#line 140 "agent_parser.yy" { // Push back the JSON value on the stack ctx.stack_.push_back(yystack_[0].value.as < ElementPtr > ()); } -#line 734 "agent_parser.cc" +#line 745 "agent_parser.cc" break; case 11: // value: "integer" -#line 142 "agent_parser.yy" +#line 146 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ElementPtr(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location))); } -#line 740 "agent_parser.cc" +#line 751 "agent_parser.cc" break; case 12: // value: "floating point" -#line 143 "agent_parser.yy" +#line 147 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ElementPtr(new DoubleElement(yystack_[0].value.as < double > (), ctx.loc2pos(yystack_[0].location))); } -#line 746 "agent_parser.cc" +#line 757 "agent_parser.cc" break; case 13: // value: "boolean" -#line 144 "agent_parser.yy" +#line 148 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ElementPtr(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location))); } -#line 752 "agent_parser.cc" +#line 763 "agent_parser.cc" break; case 14: // value: "constant string" -#line 145 "agent_parser.yy" +#line 149 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); } -#line 758 "agent_parser.cc" +#line 769 "agent_parser.cc" break; case 15: // value: "null" -#line 146 "agent_parser.yy" +#line 150 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ElementPtr(new NullElement(ctx.loc2pos(yystack_[0].location))); } -#line 764 "agent_parser.cc" +#line 775 "agent_parser.cc" break; case 16: // value: map -#line 147 "agent_parser.yy" +#line 151 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ctx.stack_.back(); ctx.stack_.pop_back(); } -#line 770 "agent_parser.cc" +#line 781 "agent_parser.cc" break; case 17: // value: list_generic -#line 148 "agent_parser.yy" +#line 152 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ctx.stack_.back(); ctx.stack_.pop_back(); } -#line 776 "agent_parser.cc" +#line 787 "agent_parser.cc" break; case 18: // $@5: %empty -#line 152 "agent_parser.yy" +#line 156 "agent_parser.yy" { // This code is executed when we're about to start parsing // the content of the map ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.push_back(m); } -#line 787 "agent_parser.cc" +#line 798 "agent_parser.cc" break; case 19: // map: "{" $@5 map_content "}" -#line 157 "agent_parser.yy" +#line 161 "agent_parser.yy" { // map parsing completed. If we ever want to do any wrap up // (maybe some sanity checking), this would be the best place // for it. } -#line 797 "agent_parser.cc" +#line 808 "agent_parser.cc" break; case 20: // map_value: map -#line 163 "agent_parser.yy" +#line 167 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ctx.stack_.back(); ctx.stack_.pop_back(); } -#line 803 "agent_parser.cc" +#line 814 "agent_parser.cc" break; case 23: // not_empty_map: "constant string" ":" value -#line 177 "agent_parser.yy" +#line 181 "agent_parser.yy" { // map containing a single entry ctx.stack_.back()->set(yystack_[2].value.as < std::string > (), yystack_[0].value.as < ElementPtr > ()); } -#line 812 "agent_parser.cc" +#line 823 "agent_parser.cc" break; case 24: // not_empty_map: not_empty_map "," "constant string" ":" value -#line 181 "agent_parser.yy" +#line 185 "agent_parser.yy" { // map consisting of a shorter map followed by // comma and string:value ctx.stack_.back()->set(yystack_[2].value.as < std::string > (), yystack_[0].value.as < ElementPtr > ()); } -#line 822 "agent_parser.cc" +#line 833 "agent_parser.cc" break; case 25: // $@6: %empty -#line 188 "agent_parser.yy" +#line 192 "agent_parser.yy" { ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.push_back(l); } -#line 831 "agent_parser.cc" +#line 842 "agent_parser.cc" break; case 26: // list_generic: "[" $@6 list_content "]" -#line 191 "agent_parser.yy" +#line 195 "agent_parser.yy" { } -#line 838 "agent_parser.cc" +#line 849 "agent_parser.cc" break; case 29: // not_empty_list: value -#line 198 "agent_parser.yy" +#line 202 "agent_parser.yy" { // List consisting of a single element. ctx.stack_.back()->add(yystack_[0].value.as < ElementPtr > ()); } -#line 847 "agent_parser.cc" +#line 858 "agent_parser.cc" break; case 30: // not_empty_list: not_empty_list "," value -#line 202 "agent_parser.yy" +#line 206 "agent_parser.yy" { // List ending with , and a value. ctx.stack_.back()->add(yystack_[0].value.as < ElementPtr > ()); } -#line 856 "agent_parser.cc" +#line 867 "agent_parser.cc" break; case 31: // unknown_map_entry: "constant string" ":" -#line 215 "agent_parser.yy" +#line 219 "agent_parser.yy" { const std::string& where = ctx.contextName(); const std::string& keyword = yystack_[1].value.as < std::string > (); error(yystack_[1].location, "got unexpected keyword \"" + keyword + "\" in " + where + " map."); } -#line 867 "agent_parser.cc" +#line 878 "agent_parser.cc" break; case 32: // $@7: %empty -#line 223 "agent_parser.yy" +#line 227 "agent_parser.yy" { // This code is executed when we're about to start parsing // the content of the map ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.push_back(m); } -#line 878 "agent_parser.cc" +#line 889 "agent_parser.cc" break; case 33: // agent_syntax_map: "{" $@7 global_objects "}" -#line 228 "agent_parser.yy" +#line 232 "agent_parser.yy" { // map parsing completed. If we ever want to do any wrap up // (maybe some sanity checking), this would be the best place // for it. } -#line 888 "agent_parser.cc" +#line 899 "agent_parser.cc" break; case 36: // $@8: %empty -#line 243 "agent_parser.yy" +#line 247 "agent_parser.yy" { // Let's create a MapElement that will represent it, add it to the @@ -900,75 +911,57 @@ namespace isc { namespace agent { ctx.stack_.push_back(m); ctx.enter(ctx.AGENT); } -#line 904 "agent_parser.cc" +#line 915 "agent_parser.cc" break; case 37: // agent_object: "Control-agent" $@8 ":" "{" global_params "}" -#line 253 "agent_parser.yy" +#line 257 "agent_parser.yy" { // Ok, we're done with parsing control-agent. Let's take the map // off the stack. ctx.stack_.pop_back(); ctx.leave(); } -#line 915 "agent_parser.cc" +#line 926 "agent_parser.cc" break; - case 50: // $@9: %empty -#line 278 "agent_parser.yy" + case 49: // $@9: %empty +#line 281 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } -#line 923 "agent_parser.cc" +#line 934 "agent_parser.cc" break; - case 51: // http_host: "http-host" $@9 ":" "constant string" -#line 280 "agent_parser.yy" + case 50: // http_host: "http-host" $@9 ":" "constant string" +#line 283 "agent_parser.yy" { ElementPtr host(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("http-host", host); ctx.leave(); } -#line 933 "agent_parser.cc" +#line 944 "agent_parser.cc" break; - case 52: // http_port: "http-port" ":" "integer" -#line 286 "agent_parser.yy" + case 51: // http_port: "http-port" ":" "integer" +#line 289 "agent_parser.yy" { ElementPtr prf(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("http-port", prf); } -#line 942 "agent_parser.cc" - break; - - case 53: // $@10: %empty -#line 291 "agent_parser.yy" - { - ctx.enter(ctx.NO_KEYWORDS); -} -#line 950 "agent_parser.cc" - break; - - case 54: // basic_authentication_realm: "basic-authentication-realm" $@10 ":" "constant string" -#line 293 "agent_parser.yy" - { - ElementPtr realm(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); - ctx.stack_.back()->set("basic-authentication-realm", realm); - ctx.leave(); -} -#line 960 "agent_parser.cc" +#line 953 "agent_parser.cc" break; - case 55: // $@11: %empty -#line 299 "agent_parser.yy" + case 52: // $@10: %empty +#line 294 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } -#line 968 "agent_parser.cc" +#line 961 "agent_parser.cc" break; - case 56: // user_context: "user-context" $@11 ":" map_value -#line 301 "agent_parser.yy" + case 53: // user_context: "user-context" $@10 ":" map_value +#line 296 "agent_parser.yy" { ElementPtr parent = ctx.stack_.back(); ElementPtr user_context = yystack_[0].value.as < ElementPtr > (); @@ -991,19 +984,19 @@ namespace isc { namespace agent { parent->set("user-context", user_context); ctx.leave(); } -#line 995 "agent_parser.cc" +#line 988 "agent_parser.cc" break; - case 57: // $@12: %empty -#line 324 "agent_parser.yy" + case 54: // $@11: %empty +#line 319 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } -#line 1003 "agent_parser.cc" +#line 996 "agent_parser.cc" break; - case 58: // comment: "comment" $@12 ":" "constant string" -#line 326 "agent_parser.yy" + case 55: // comment: "comment" $@11 ":" "constant string" +#line 321 "agent_parser.yy" { ElementPtr parent = ctx.stack_.back(); ElementPtr user_context(new MapElement(ctx.loc2pos(yystack_[3].location))); @@ -1028,463 +1021,530 @@ namespace isc { namespace agent { parent->set("user-context", user_context); ctx.leave(); } -#line 1032 "agent_parser.cc" +#line 1025 "agent_parser.cc" break; - case 59: // $@13: %empty -#line 352 "agent_parser.yy" + case 56: // $@12: %empty +#line 347 "agent_parser.yy" { ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("hooks-libraries", l); ctx.stack_.push_back(l); ctx.enter(ctx.HOOKS_LIBRARIES); } -#line 1043 "agent_parser.cc" +#line 1036 "agent_parser.cc" break; - case 60: // hooks_libraries: "hooks-libraries" $@13 ":" "[" hooks_libraries_list "]" -#line 357 "agent_parser.yy" + case 57: // hooks_libraries: "hooks-libraries" $@12 ":" "[" hooks_libraries_list "]" +#line 352 "agent_parser.yy" { ctx.stack_.pop_back(); ctx.leave(); } -#line 1052 "agent_parser.cc" +#line 1045 "agent_parser.cc" break; - case 65: // $@14: %empty -#line 370 "agent_parser.yy" + case 62: // $@13: %empty +#line 365 "agent_parser.yy" { ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->add(m); ctx.stack_.push_back(m); } -#line 1062 "agent_parser.cc" +#line 1055 "agent_parser.cc" break; - case 66: // hooks_library: "{" $@14 hooks_params "}" -#line 374 "agent_parser.yy" + case 63: // hooks_library: "{" $@13 hooks_params "}" +#line 369 "agent_parser.yy" { ctx.stack_.pop_back(); } -#line 1070 "agent_parser.cc" +#line 1063 "agent_parser.cc" break; - case 72: // $@15: %empty -#line 387 "agent_parser.yy" + case 69: // $@14: %empty +#line 382 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } -#line 1078 "agent_parser.cc" +#line 1071 "agent_parser.cc" break; - case 73: // library: "library" $@15 ":" "constant string" -#line 389 "agent_parser.yy" + case 70: // library: "library" $@14 ":" "constant string" +#line 384 "agent_parser.yy" { ElementPtr lib(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("library", lib); ctx.leave(); } -#line 1088 "agent_parser.cc" +#line 1081 "agent_parser.cc" break; - case 74: // $@16: %empty -#line 395 "agent_parser.yy" + case 71: // $@15: %empty +#line 390 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } -#line 1096 "agent_parser.cc" +#line 1089 "agent_parser.cc" break; - case 75: // parameters: "parameters" $@16 ":" map_value -#line 397 "agent_parser.yy" + case 72: // parameters: "parameters" $@15 ":" map_value +#line 392 "agent_parser.yy" { ctx.stack_.back()->set("parameters", yystack_[0].value.as < ElementPtr > ()); ctx.leave(); } -#line 1105 "agent_parser.cc" +#line 1098 "agent_parser.cc" break; - case 76: // $@17: %empty -#line 405 "agent_parser.yy" + case 73: // $@16: %empty +#line 400 "agent_parser.yy" { ElementPtr m(new MapElement(ctx.loc2pos(yystack_[2].location))); ctx.stack_.back()->set("control-sockets", m); ctx.stack_.push_back(m); ctx.enter(ctx.CONTROL_SOCKETS); } -#line 1116 "agent_parser.cc" +#line 1109 "agent_parser.cc" break; - case 77: // control_sockets: "control-sockets" ":" "{" $@17 control_sockets_params "}" -#line 410 "agent_parser.yy" + case 74: // control_sockets: "control-sockets" ":" "{" $@16 control_sockets_params "}" +#line 405 "agent_parser.yy" { ctx.stack_.pop_back(); ctx.leave(); } -#line 1125 "agent_parser.cc" +#line 1118 "agent_parser.cc" break; - case 84: // $@18: %empty -#line 431 "agent_parser.yy" + case 81: // $@17: %empty +#line 426 "agent_parser.yy" { ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("dhcp4", m); ctx.stack_.push_back(m); ctx.enter(ctx.SERVER); } -#line 1136 "agent_parser.cc" +#line 1129 "agent_parser.cc" break; - case 85: // dhcp4_server_socket: "dhcp4" $@18 ":" "{" control_socket_params "}" -#line 436 "agent_parser.yy" + case 82: // dhcp4_server_socket: "dhcp4" $@17 ":" "{" control_socket_params "}" +#line 431 "agent_parser.yy" { ctx.stack_.pop_back(); ctx.leave(); } -#line 1145 "agent_parser.cc" +#line 1138 "agent_parser.cc" break; - case 86: // $@19: %empty -#line 442 "agent_parser.yy" + case 83: // $@18: %empty +#line 437 "agent_parser.yy" { ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("dhcp6", m); ctx.stack_.push_back(m); ctx.enter(ctx.SERVER); } -#line 1156 "agent_parser.cc" +#line 1149 "agent_parser.cc" break; - case 87: // dhcp6_server_socket: "dhcp6" $@19 ":" "{" control_socket_params "}" -#line 447 "agent_parser.yy" + case 84: // dhcp6_server_socket: "dhcp6" $@18 ":" "{" control_socket_params "}" +#line 442 "agent_parser.yy" { ctx.stack_.pop_back(); ctx.leave(); } -#line 1165 "agent_parser.cc" +#line 1158 "agent_parser.cc" break; - case 88: // $@20: %empty -#line 453 "agent_parser.yy" + case 85: // $@19: %empty +#line 448 "agent_parser.yy" { ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("d2", m); ctx.stack_.push_back(m); ctx.enter(ctx.SERVER); } -#line 1176 "agent_parser.cc" +#line 1169 "agent_parser.cc" break; - case 89: // d2_server_socket: "d2" $@20 ":" "{" control_socket_params "}" -#line 458 "agent_parser.yy" + case 86: // d2_server_socket: "d2" $@19 ":" "{" control_socket_params "}" +#line 453 "agent_parser.yy" { ctx.stack_.pop_back(); ctx.leave(); } -#line 1185 "agent_parser.cc" +#line 1178 "agent_parser.cc" break; - case 97: // $@21: %empty -#line 477 "agent_parser.yy" + case 94: // $@20: %empty +#line 472 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } -#line 1193 "agent_parser.cc" +#line 1186 "agent_parser.cc" break; - case 98: // socket_name: "socket-name" $@21 ":" "constant string" -#line 479 "agent_parser.yy" + case 95: // socket_name: "socket-name" $@20 ":" "constant string" +#line 474 "agent_parser.yy" { ElementPtr name(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("socket-name", name); ctx.leave(); } -#line 1203 "agent_parser.cc" +#line 1196 "agent_parser.cc" break; - case 99: // $@22: %empty -#line 486 "agent_parser.yy" + case 96: // $@21: %empty +#line 481 "agent_parser.yy" { ctx.enter(ctx.SOCKET_TYPE); } -#line 1211 "agent_parser.cc" +#line 1204 "agent_parser.cc" break; - case 100: // socket_type: "socket-type" $@22 ":" socket_type_value -#line 488 "agent_parser.yy" + case 97: // socket_type: "socket-type" $@21 ":" socket_type_value +#line 483 "agent_parser.yy" { ctx.stack_.back()->set("socket-type", yystack_[0].value.as < ElementPtr > ()); ctx.leave(); } -#line 1220 "agent_parser.cc" +#line 1213 "agent_parser.cc" break; - case 101: // socket_type_value: "unix" -#line 494 "agent_parser.yy" + case 98: // socket_type_value: "unix" +#line 489 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement("unix", ctx.loc2pos(yystack_[0].location))); } -#line 1226 "agent_parser.cc" +#line 1219 "agent_parser.cc" + break; + + case 99: // $@22: %empty +#line 496 "agent_parser.yy" + { + // Add unique here + ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location))); + ctx.stack_.back()->set("authentication", m); + ctx.stack_.push_back(m); + ctx.enter(ctx.AUTHENTICATION); +} +#line 1231 "agent_parser.cc" + break; + + case 100: // authentication: "authentication" $@22 ":" "{" auth_params "}" +#line 502 "agent_parser.yy" + { + // The type parameter is required + ctx.require("type", ctx.loc2pos(yystack_[2].location), ctx.loc2pos(yystack_[0].location)); + ctx.stack_.pop_back(); + ctx.leave(); +} +#line 1242 "agent_parser.cc" + break; + + case 106: // $@23: %empty +#line 518 "agent_parser.yy" + { + // Add unique here + ctx.enter(ctx.AUTH_TYPE); +} +#line 1251 "agent_parser.cc" break; - case 102: // $@23: %empty -#line 501 "agent_parser.yy" - { + case 107: // auth_type: "type" $@23 ":" auth_type_value +#line 521 "agent_parser.yy" + { + ctx.stack_.back()->set("type", yystack_[0].value.as < ElementPtr > ()); + ctx.leave(); +} +#line 1260 "agent_parser.cc" + break; + + case 108: // auth_type_value: "basic" +#line 526 "agent_parser.yy" + { yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement("basic", ctx.loc2pos(yystack_[0].location))); } +#line 1266 "agent_parser.cc" + break; + + case 109: // $@24: %empty +#line 529 "agent_parser.yy" + { + // Add unique here + ctx.enter(ctx.NO_KEYWORD); +} +#line 1275 "agent_parser.cc" + break; + + case 110: // realm: "realm" $@24 ":" "constant string" +#line 532 "agent_parser.yy" + { + ElementPtr realm(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); + ctx.stack_.back()->set("realm", realm); + ctx.leave(); +} +#line 1285 "agent_parser.cc" + break; + + case 111: // $@25: %empty +#line 538 "agent_parser.yy" + { + // Add unique here ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location))); - ctx.stack_.back()->set("basic-authentications", l); + ctx.stack_.back()->set("clients", l); ctx.stack_.push_back(l); - ctx.enter(ctx.BASIC_AUTHENTICATIONS); + ctx.enter(ctx.CLIENTS); } -#line 1237 "agent_parser.cc" +#line 1297 "agent_parser.cc" break; - case 103: // basic_authentications: "basic-authentications" $@23 ":" "[" basic_auth_list "]" -#line 506 "agent_parser.yy" - { + case 112: // clients: "clients" $@25 ":" "[" clients_list "]" +#line 544 "agent_parser.yy" + { ctx.stack_.pop_back(); ctx.leave(); } -#line 1246 "agent_parser.cc" +#line 1306 "agent_parser.cc" break; - case 108: // $@24: %empty -#line 519 "agent_parser.yy" + case 117: // $@26: %empty +#line 557 "agent_parser.yy" { ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->add(m); ctx.stack_.push_back(m); } -#line 1256 "agent_parser.cc" +#line 1316 "agent_parser.cc" break; - case 109: // basic_auth: "{" $@24 basic_auth_params "}" -#line 523 "agent_parser.yy" - { + case 118: // basic_auth: "{" $@26 clients_params "}" +#line 561 "agent_parser.yy" + { ctx.stack_.pop_back(); } -#line 1264 "agent_parser.cc" +#line 1324 "agent_parser.cc" break; - case 117: // $@25: %empty -#line 538 "agent_parser.yy" + case 126: // $@27: %empty +#line 576 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } -#line 1272 "agent_parser.cc" +#line 1332 "agent_parser.cc" break; - case 118: // user: "user" $@25 ":" "constant string" -#line 540 "agent_parser.yy" + case 127: // user: "user" $@27 ":" "constant string" +#line 578 "agent_parser.yy" { ElementPtr user(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("user", user); ctx.leave(); } -#line 1282 "agent_parser.cc" +#line 1342 "agent_parser.cc" break; - case 119: // $@26: %empty -#line 546 "agent_parser.yy" + case 128: // $@28: %empty +#line 584 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } -#line 1290 "agent_parser.cc" +#line 1350 "agent_parser.cc" break; - case 120: // password: "password" $@26 ":" "constant string" -#line 548 "agent_parser.yy" + case 129: // password: "password" $@28 ":" "constant string" +#line 586 "agent_parser.yy" { ElementPtr password(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("password", password); ctx.leave(); } -#line 1300 "agent_parser.cc" +#line 1360 "agent_parser.cc" break; - case 121: // $@27: %empty -#line 558 "agent_parser.yy" + case 130: // $@29: %empty +#line 596 "agent_parser.yy" { ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("loggers", l); ctx.stack_.push_back(l); ctx.enter(ctx.LOGGERS); } -#line 1311 "agent_parser.cc" +#line 1371 "agent_parser.cc" break; - case 122: // loggers: "loggers" $@27 ":" "[" loggers_entries "]" -#line 563 "agent_parser.yy" + case 131: // loggers: "loggers" $@29 ":" "[" loggers_entries "]" +#line 601 "agent_parser.yy" { ctx.stack_.pop_back(); ctx.leave(); } -#line 1320 "agent_parser.cc" +#line 1380 "agent_parser.cc" break; - case 125: // $@28: %empty -#line 575 "agent_parser.yy" + case 134: // $@30: %empty +#line 613 "agent_parser.yy" { ElementPtr l(new MapElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->add(l); ctx.stack_.push_back(l); } -#line 1330 "agent_parser.cc" +#line 1390 "agent_parser.cc" break; - case 126: // logger_entry: "{" $@28 logger_params "}" -#line 579 "agent_parser.yy" + case 135: // logger_entry: "{" $@30 logger_params "}" +#line 617 "agent_parser.yy" { ctx.stack_.pop_back(); } -#line 1338 "agent_parser.cc" +#line 1398 "agent_parser.cc" break; - case 136: // $@29: %empty -#line 596 "agent_parser.yy" + case 145: // $@31: %empty +#line 634 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } -#line 1346 "agent_parser.cc" +#line 1406 "agent_parser.cc" break; - case 137: // name: "name" $@29 ":" "constant string" -#line 598 "agent_parser.yy" + case 146: // name: "name" $@31 ":" "constant string" +#line 636 "agent_parser.yy" { ElementPtr name(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("name", name); ctx.leave(); } -#line 1356 "agent_parser.cc" +#line 1416 "agent_parser.cc" break; - case 138: // debuglevel: "debuglevel" ":" "integer" -#line 604 "agent_parser.yy" + case 147: // debuglevel: "debuglevel" ":" "integer" +#line 642 "agent_parser.yy" { ElementPtr dl(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("debuglevel", dl); } -#line 1365 "agent_parser.cc" +#line 1425 "agent_parser.cc" break; - case 139: // $@30: %empty -#line 609 "agent_parser.yy" + case 148: // $@32: %empty +#line 647 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } -#line 1373 "agent_parser.cc" +#line 1433 "agent_parser.cc" break; - case 140: // severity: "severity" $@30 ":" "constant string" -#line 611 "agent_parser.yy" + case 149: // severity: "severity" $@32 ":" "constant string" +#line 649 "agent_parser.yy" { ElementPtr sev(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("severity", sev); ctx.leave(); } -#line 1383 "agent_parser.cc" +#line 1443 "agent_parser.cc" break; - case 141: // $@31: %empty -#line 617 "agent_parser.yy" + case 150: // $@33: %empty +#line 655 "agent_parser.yy" { ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("output_options", l); ctx.stack_.push_back(l); ctx.enter(ctx.OUTPUT_OPTIONS); } -#line 1394 "agent_parser.cc" +#line 1454 "agent_parser.cc" break; - case 142: // output_options_list: "output_options" $@31 ":" "[" output_options_list_content "]" -#line 622 "agent_parser.yy" + case 151: // output_options_list: "output_options" $@33 ":" "[" output_options_list_content "]" +#line 660 "agent_parser.yy" { ctx.stack_.pop_back(); ctx.leave(); } -#line 1403 "agent_parser.cc" +#line 1463 "agent_parser.cc" break; - case 145: // $@32: %empty -#line 631 "agent_parser.yy" + case 154: // $@34: %empty +#line 669 "agent_parser.yy" { ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->add(m); ctx.stack_.push_back(m); } -#line 1413 "agent_parser.cc" +#line 1473 "agent_parser.cc" break; - case 146: // output_entry: "{" $@32 output_params_list "}" -#line 635 "agent_parser.yy" + case 155: // output_entry: "{" $@34 output_params_list "}" +#line 673 "agent_parser.yy" { ctx.stack_.pop_back(); } -#line 1421 "agent_parser.cc" +#line 1481 "agent_parser.cc" break; - case 154: // $@33: %empty -#line 650 "agent_parser.yy" + case 163: // $@35: %empty +#line 688 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } -#line 1429 "agent_parser.cc" +#line 1489 "agent_parser.cc" break; - case 155: // output: "output" $@33 ":" "constant string" -#line 652 "agent_parser.yy" + case 164: // output: "output" $@35 ":" "constant string" +#line 690 "agent_parser.yy" { ElementPtr sev(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("output", sev); ctx.leave(); } -#line 1439 "agent_parser.cc" +#line 1499 "agent_parser.cc" break; - case 156: // flush: "flush" ":" "boolean" -#line 658 "agent_parser.yy" + case 165: // flush: "flush" ":" "boolean" +#line 696 "agent_parser.yy" { ElementPtr flush(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("flush", flush); } -#line 1448 "agent_parser.cc" +#line 1508 "agent_parser.cc" break; - case 157: // maxsize: "maxsize" ":" "integer" -#line 663 "agent_parser.yy" + case 166: // maxsize: "maxsize" ":" "integer" +#line 701 "agent_parser.yy" { ElementPtr maxsize(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("maxsize", maxsize); } -#line 1457 "agent_parser.cc" +#line 1517 "agent_parser.cc" break; - case 158: // maxver: "maxver" ":" "integer" -#line 668 "agent_parser.yy" + case 167: // maxver: "maxver" ":" "integer" +#line 706 "agent_parser.yy" { ElementPtr maxver(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("maxver", maxver); } -#line 1466 "agent_parser.cc" +#line 1526 "agent_parser.cc" break; - case 159: // $@34: %empty -#line 673 "agent_parser.yy" + case 168: // $@36: %empty +#line 711 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } -#line 1474 "agent_parser.cc" +#line 1534 "agent_parser.cc" break; - case 160: // pattern: "pattern" $@34 ":" "constant string" -#line 675 "agent_parser.yy" + case 169: // pattern: "pattern" $@36 ":" "constant string" +#line 713 "agent_parser.yy" { ElementPtr sev(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("pattern", sev); ctx.leave(); } -#line 1484 "agent_parser.cc" +#line 1544 "agent_parser.cc" break; -#line 1488 "agent_parser.cc" +#line 1548 "agent_parser.cc" default: break; @@ -1833,40 +1893,42 @@ namespace isc { namespace agent { } - const short AgentParser::yypact_ninf_ = -140; + const short AgentParser::yypact_ninf_ = -133; const signed char AgentParser::yytable_ninf_ = -1; const short AgentParser::yypact_[] = { - 75, -140, -140, -140, 4, 2, 1, 3, -140, -140, - -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, - -140, -140, -140, -140, 2, -36, 39, 6, -140, 56, - 9, 59, 62, 61, -140, 63, -140, -140, -140, 98, - -140, -140, -140, 100, -140, -140, -140, 105, -140, 28, - -140, -140, -140, -140, -140, -140, -140, -140, -140, -140, - -140, 2, 2, -140, 50, 106, -140, 113, 80, 114, - 115, 116, 92, 117, 118, 120, -140, 6, -140, -140, - -140, 121, 122, 89, -140, 90, 123, 91, -140, 129, - 130, 131, -140, 2, 6, -140, -140, -140, -140, -140, - 41, 132, 133, 134, -140, 58, -140, -140, -140, -140, - 76, -140, -140, -140, -140, -140, 136, 124, -140, -140, - 137, 125, -140, -140, 94, -140, -140, 140, 141, 142, - 41, -140, -1, -140, 132, -12, -140, 133, 23, 134, - -140, 143, 144, 145, -140, -140, -140, -140, -140, -140, - 77, -140, -140, -140, -140, -140, -140, -140, 78, -140, - -140, -140, -140, -140, -140, 149, -140, -140, -140, -140, - 79, -140, -140, -140, -140, -140, -140, 13, 13, 13, - 150, 154, -1, -140, 155, 156, -2, -140, 157, 158, - 104, 159, 23, -140, -140, -140, -140, -140, -140, 85, - -140, -140, -140, 86, 87, 96, 107, -140, 126, 123, - -140, 127, 165, -140, 135, -140, 160, 167, 13, -140, - -140, -140, -140, -140, -140, -140, -140, 166, -140, 138, - 152, -140, -140, 95, -140, -140, -140, -140, 40, 166, - -140, -140, 168, 171, 172, -140, 88, -140, -140, -140, - -140, -140, -140, -140, 174, 103, 139, 146, 175, 40, - -140, 148, -140, -140, -140, 151, -140, -140, -140 + 59, -133, -133, -133, 8, 5, 6, 13, -133, -133, + -133, -133, -133, -133, -133, -133, -133, -133, -133, -133, + -133, -133, -133, -133, 5, -34, 18, 10, -133, 48, + 83, 58, 96, 102, -133, 98, -133, -133, -133, 104, + -133, -133, -133, 106, -133, -133, 107, -133, 1, -133, + -133, -133, -133, -133, -133, -133, -133, -133, -133, 5, + 5, -133, 70, 112, -133, 113, 72, 115, 116, 117, + 118, 119, 120, -133, 10, -133, -133, -133, 123, 121, + 88, -133, 122, 89, 124, -133, 125, 127, -133, 5, + 10, -133, -133, -133, -133, 80, -8, 128, 129, -133, + 28, -133, -133, -133, 73, -133, -133, -133, -133, -133, + -133, -133, -133, 74, -133, -133, -133, -133, -133, 131, + 135, -133, -133, 55, -133, -133, 136, 137, 138, 80, + -133, 139, 140, 141, -8, -133, -12, -133, 128, -7, + 129, -133, 105, 101, 134, -133, 142, 143, 144, -133, + -133, -133, -133, 75, -133, -133, -133, -133, -133, -133, + 148, -133, -133, -133, -133, 76, -133, -133, -133, -133, + -133, -133, -133, -133, -133, 146, 30, 30, 30, 150, + 151, 4, -133, 152, 153, 126, 154, -7, -133, -133, + 157, 145, -133, -133, -133, -133, -133, -133, 77, -133, + -133, -133, 84, 85, 114, 122, -133, 130, 159, -133, + 132, -133, 46, -133, 146, 161, 162, 30, -133, -133, + -133, -133, -133, -133, 160, -133, -133, -133, -133, -133, + -133, 86, -133, -133, -133, -133, 133, 155, -133, -133, + 94, -133, 164, 165, 46, -133, -133, -133, -133, 33, + 160, -133, 147, 149, -133, -133, 166, 167, 169, -133, + 87, -133, -133, -133, -133, -133, -133, -133, -133, -133, + 170, 99, 156, 158, 172, 33, -133, 163, -133, -133, + -133, 168, -133, -133, -133 }; const unsigned char @@ -1875,166 +1937,174 @@ namespace isc { namespace agent { 0, 2, 4, 6, 0, 0, 0, 0, 1, 25, 18, 15, 14, 11, 12, 13, 3, 10, 16, 17, 32, 5, 8, 7, 27, 21, 0, 0, 29, 0, - 28, 0, 0, 22, 36, 0, 34, 35, 50, 0, - 53, 55, 57, 0, 102, 59, 121, 0, 49, 0, - 38, 40, 41, 42, 47, 48, 45, 43, 44, 46, - 26, 0, 0, 19, 0, 0, 33, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 31, 0, 9, 30, - 23, 0, 0, 0, 52, 0, 0, 0, 76, 0, - 0, 0, 39, 0, 0, 51, 54, 20, 56, 58, - 0, 104, 61, 0, 24, 0, 84, 86, 88, 83, - 0, 78, 80, 81, 82, 108, 0, 105, 106, 65, - 0, 62, 63, 125, 0, 123, 37, 0, 0, 0, - 0, 77, 0, 103, 0, 0, 60, 0, 0, 0, - 122, 0, 0, 0, 79, 117, 119, 116, 114, 115, - 0, 110, 112, 113, 107, 72, 74, 69, 0, 67, - 70, 71, 64, 136, 141, 0, 139, 135, 133, 134, - 0, 127, 129, 131, 132, 130, 124, 0, 0, 0, - 0, 0, 0, 109, 0, 0, 0, 66, 0, 0, - 0, 0, 0, 126, 97, 99, 96, 94, 95, 0, - 90, 92, 93, 0, 0, 0, 0, 111, 0, 0, - 68, 0, 0, 138, 0, 128, 0, 0, 0, 85, - 87, 89, 118, 120, 73, 75, 137, 0, 140, 0, - 0, 91, 145, 0, 143, 98, 101, 100, 0, 0, - 142, 154, 0, 0, 0, 159, 0, 147, 149, 150, - 151, 152, 153, 144, 0, 0, 0, 0, 0, 0, - 146, 0, 156, 157, 158, 0, 148, 155, 160 + 28, 0, 0, 22, 36, 0, 34, 35, 49, 0, + 52, 54, 99, 0, 56, 130, 0, 48, 0, 38, + 40, 41, 46, 47, 44, 43, 42, 45, 26, 0, + 0, 19, 0, 0, 33, 0, 0, 0, 0, 0, + 0, 0, 0, 31, 0, 9, 30, 23, 0, 0, + 0, 51, 0, 0, 0, 73, 0, 0, 39, 0, + 0, 50, 20, 53, 55, 0, 0, 58, 0, 24, + 0, 106, 109, 111, 0, 101, 103, 104, 105, 81, + 83, 85, 80, 0, 75, 77, 78, 79, 62, 0, + 59, 60, 134, 0, 132, 37, 0, 0, 0, 0, + 100, 0, 0, 0, 0, 74, 0, 57, 0, 0, + 0, 131, 0, 0, 0, 102, 0, 0, 0, 76, + 69, 71, 66, 0, 64, 67, 68, 61, 145, 150, + 0, 148, 144, 142, 143, 0, 136, 138, 140, 141, + 139, 133, 108, 107, 110, 113, 0, 0, 0, 0, + 0, 0, 63, 0, 0, 0, 0, 0, 135, 117, + 0, 114, 115, 94, 96, 93, 91, 92, 0, 87, + 89, 90, 0, 0, 0, 0, 65, 0, 0, 147, + 0, 137, 0, 112, 0, 0, 0, 0, 82, 84, + 86, 70, 72, 146, 0, 149, 126, 128, 125, 123, + 124, 0, 119, 121, 122, 116, 0, 0, 88, 154, + 0, 152, 0, 0, 0, 118, 95, 98, 97, 0, + 0, 151, 0, 0, 120, 163, 0, 0, 0, 168, + 0, 156, 158, 159, 160, 161, 162, 153, 127, 129, + 0, 0, 0, 0, 0, 0, 155, 0, 165, 166, + 167, 0, 157, 164, 169 }; const short AgentParser::yypgoto_[] = { - -140, -140, -140, -140, -140, -140, -140, -140, -19, -83, - -140, -72, -140, -140, -140, -140, -140, -140, -27, -140, - -140, -140, -140, -140, -140, 93, 108, -140, -140, -140, - -140, -140, -26, -140, -25, -140, -140, -140, -140, -140, - 44, -140, -140, -3, -140, -140, -140, -140, -140, -140, - -140, 54, -140, -140, -140, -140, -140, -140, -139, -32, - -140, -140, -140, -140, -140, -140, -140, -140, -140, 57, - -140, -140, 10, -140, -140, -140, -140, -140, -140, -140, - 49, -140, -140, 5, -140, -140, -140, -140, -140, -140, - -140, -140, -45, -140, -140, -64, -140, -140, -140, -140, - -140, -140, -140 + -133, -133, -133, -133, -133, -133, -133, -133, -19, -79, + -133, -24, -133, -133, -133, -133, -133, -133, -27, -133, + -133, -133, -133, -133, -133, 90, 108, -133, -133, -133, + -26, -133, -25, -133, -133, -133, -133, -133, 41, -133, + -133, 3, -133, -133, -133, -133, -133, -133, -133, 54, + -133, -133, -133, -133, -133, -133, -132, -28, -133, -133, + -133, -133, -133, -133, -133, -133, 61, -133, -133, -133, + -133, -133, -133, -133, -133, -133, -23, -133, -133, -51, + -133, -133, -133, -133, -133, -133, -133, 56, -133, -133, + 11, -133, -133, -133, -133, -133, -133, -133, -133, -55, + -133, -133, -78, -133, -133, -133, -133, -133, -133, -133 }; const short AgentParser::yydefgoto_[] = { -1, 4, 5, 6, 7, 23, 27, 16, 17, 18, - 25, 98, 32, 33, 19, 24, 29, 30, 196, 21, - 26, 35, 36, 37, 65, 49, 50, 51, 67, 52, - 53, 69, 197, 70, 198, 71, 56, 74, 120, 121, - 122, 135, 158, 159, 160, 184, 161, 185, 57, 100, - 110, 111, 112, 127, 113, 128, 114, 129, 199, 200, - 201, 216, 202, 217, 237, 58, 73, 116, 117, 118, - 132, 150, 151, 152, 180, 153, 181, 59, 75, 124, - 125, 138, 170, 171, 172, 188, 173, 174, 191, 175, - 189, 233, 234, 238, 246, 247, 248, 254, 249, 250, - 251, 252, 258 + 25, 93, 32, 33, 19, 24, 29, 30, 195, 21, + 26, 35, 36, 37, 63, 48, 49, 50, 65, 51, + 196, 67, 197, 68, 54, 71, 119, 120, 121, 136, + 153, 154, 155, 179, 156, 180, 55, 96, 113, 114, + 115, 131, 116, 132, 117, 133, 198, 199, 200, 215, + 201, 216, 248, 56, 69, 104, 105, 106, 126, 173, + 107, 127, 108, 128, 190, 191, 192, 212, 231, 232, + 233, 242, 234, 243, 57, 72, 123, 124, 139, 165, + 166, 167, 183, 168, 169, 186, 170, 184, 240, 241, + 249, 260, 261, 262, 270, 263, 264, 265, 266, 274 }; const short AgentParser::yytable_[] = { - 48, 54, 55, 97, 8, 28, 31, 9, 20, 10, - 22, 11, 61, 41, 42, 155, 156, 38, 39, 40, - 41, 42, 43, 145, 146, 155, 156, 41, 42, 44, - 47, 77, 45, 194, 195, 46, 78, 41, 42, 203, - 204, 47, 79, 80, 12, 13, 14, 15, 47, 34, - 48, 54, 55, 163, 164, 47, 165, 166, 106, 107, - 108, 77, 60, 62, 64, 47, 126, 48, 54, 55, - 63, 66, 241, 109, 104, 242, 243, 244, 245, 130, - 182, 186, 192, 47, 131, 183, 187, 193, 218, 218, - 218, 259, 81, 219, 220, 221, 260, 139, 239, 88, - 140, 240, 68, 109, 72, 147, 148, 149, 157, 76, - 82, 167, 168, 169, 1, 2, 3, 83, 85, 86, - 87, 89, 90, 84, 91, 93, 97, 134, 137, 94, - 10, 95, 96, 99, 101, 102, 103, 225, 222, 115, - 119, 123, 133, 136, 141, 142, 143, 213, 262, 223, - 177, 178, 179, 190, 205, 147, 148, 149, 206, 208, - 209, 211, 212, 214, 229, 167, 168, 169, 224, 226, - 227, 230, 255, 232, 236, 256, 257, 228, 261, 265, - 235, 162, 263, 210, 144, 92, 231, 105, 176, 264, - 267, 154, 207, 268, 253, 266, 0, 215 + 47, 52, 53, 92, 74, 28, 40, 41, 8, 75, + 9, 31, 10, 20, 11, 109, 110, 111, 150, 151, + 22, 38, 39, 40, 41, 42, 158, 159, 34, 160, + 161, 74, 43, 46, 150, 151, 125, 46, 46, 44, + 76, 77, 45, 40, 41, 202, 203, 47, 52, 53, + 12, 13, 14, 15, 58, 46, 193, 194, 140, 40, + 41, 141, 60, 47, 52, 53, 226, 227, 255, 112, + 99, 256, 257, 258, 259, 46, 129, 134, 181, 187, + 217, 130, 135, 182, 188, 218, 59, 217, 217, 244, + 275, 46, 219, 220, 245, 276, 101, 250, 102, 103, + 251, 1, 2, 3, 61, 62, 64, 112, 66, 152, + 70, 73, 162, 163, 164, 78, 79, 80, 81, 82, + 83, 84, 172, 86, 87, 85, 92, 89, 90, 10, + 97, 95, 98, 91, 94, 118, 122, 137, 138, 175, + 142, 143, 144, 146, 147, 148, 174, 278, 214, 176, + 177, 178, 185, 189, 204, 205, 207, 208, 210, 221, + 162, 163, 164, 213, 224, 236, 237, 239, 252, 253, + 271, 272, 209, 273, 277, 223, 281, 225, 246, 157, + 100, 222, 88, 247, 206, 228, 229, 230, 149, 238, + 145, 235, 268, 254, 269, 267, 171, 282, 211, 0, + 0, 0, 279, 0, 280, 0, 0, 0, 283, 0, + 0, 0, 0, 284, 0, 0, 0, 228, 229, 230 }; const short AgentParser::yycheck_[] = { - 27, 27, 27, 86, 0, 24, 42, 5, 7, 7, - 7, 9, 3, 14, 15, 27, 28, 11, 12, 13, - 14, 15, 16, 24, 25, 27, 28, 14, 15, 23, - 42, 3, 26, 20, 21, 29, 8, 14, 15, 178, - 179, 42, 61, 62, 42, 43, 44, 45, 42, 10, - 77, 77, 77, 30, 31, 42, 33, 34, 17, 18, - 19, 3, 6, 4, 3, 42, 8, 94, 94, 94, - 8, 8, 32, 100, 93, 35, 36, 37, 38, 3, - 3, 3, 3, 42, 8, 8, 8, 8, 3, 3, - 3, 3, 42, 8, 8, 8, 8, 3, 3, 7, - 6, 6, 4, 130, 4, 132, 132, 132, 135, 4, - 4, 138, 138, 138, 39, 40, 41, 4, 4, 4, - 4, 4, 4, 43, 4, 4, 209, 3, 3, 7, - 7, 42, 42, 42, 5, 5, 5, 209, 42, 7, - 7, 7, 6, 6, 4, 4, 4, 43, 45, 42, - 7, 7, 7, 4, 4, 182, 182, 182, 4, 4, - 4, 4, 4, 4, 4, 192, 192, 192, 42, 42, - 5, 4, 4, 7, 22, 4, 4, 42, 4, 4, - 42, 137, 43, 186, 130, 77, 218, 94, 139, 43, - 42, 134, 182, 42, 239, 259, -1, 192 + 27, 27, 27, 82, 3, 24, 13, 14, 0, 8, + 5, 45, 7, 7, 9, 23, 24, 25, 30, 31, + 7, 11, 12, 13, 14, 15, 33, 34, 10, 36, + 37, 3, 22, 45, 30, 31, 8, 45, 45, 29, + 59, 60, 32, 13, 14, 177, 178, 74, 74, 74, + 45, 46, 47, 48, 6, 45, 26, 27, 3, 13, + 14, 6, 4, 90, 90, 90, 20, 21, 35, 96, + 89, 38, 39, 40, 41, 45, 3, 3, 3, 3, + 3, 8, 8, 8, 8, 8, 3, 3, 3, 3, + 3, 45, 8, 8, 8, 8, 16, 3, 18, 19, + 6, 42, 43, 44, 8, 3, 8, 134, 4, 136, + 4, 4, 139, 139, 139, 45, 4, 4, 46, 4, + 4, 4, 17, 4, 4, 7, 205, 4, 7, 7, + 5, 7, 5, 45, 45, 7, 7, 6, 3, 5, + 4, 4, 4, 4, 4, 4, 45, 48, 3, 7, + 7, 7, 4, 7, 4, 4, 4, 4, 4, 45, + 187, 187, 187, 6, 5, 4, 4, 7, 4, 4, + 4, 4, 46, 4, 4, 45, 4, 45, 45, 138, + 90, 205, 74, 28, 181, 212, 212, 212, 134, 217, + 129, 214, 45, 244, 45, 250, 140, 275, 187, -1, + -1, -1, 46, -1, 46, -1, -1, -1, 45, -1, + -1, -1, -1, 45, -1, -1, -1, 244, 244, 244 }; const unsigned char AgentParser::yystos_[] = { - 0, 39, 40, 41, 47, 48, 49, 50, 0, 5, - 7, 9, 42, 43, 44, 45, 53, 54, 55, 60, - 7, 65, 7, 51, 61, 56, 66, 52, 54, 62, - 63, 42, 58, 59, 10, 67, 68, 69, 11, 12, - 13, 14, 15, 16, 23, 26, 29, 42, 64, 71, - 72, 73, 75, 76, 78, 80, 82, 94, 111, 123, - 6, 3, 4, 8, 3, 70, 8, 74, 4, 77, - 79, 81, 4, 112, 83, 124, 4, 3, 8, 54, - 54, 42, 4, 4, 43, 4, 4, 4, 7, 4, - 4, 4, 72, 4, 7, 42, 42, 55, 57, 42, - 95, 5, 5, 5, 54, 71, 17, 18, 19, 64, - 96, 97, 98, 100, 102, 7, 113, 114, 115, 7, - 84, 85, 86, 7, 125, 126, 8, 99, 101, 103, - 3, 8, 116, 6, 3, 87, 6, 3, 127, 3, - 6, 4, 4, 4, 97, 24, 25, 64, 78, 80, - 117, 118, 119, 121, 115, 27, 28, 64, 88, 89, - 90, 92, 86, 30, 31, 33, 34, 64, 78, 80, - 128, 129, 130, 132, 133, 135, 126, 7, 7, 7, - 120, 122, 3, 8, 91, 93, 3, 8, 131, 136, - 4, 134, 3, 8, 20, 21, 64, 78, 80, 104, - 105, 106, 108, 104, 104, 4, 4, 118, 4, 4, - 89, 4, 4, 43, 4, 129, 107, 109, 3, 8, - 8, 8, 42, 42, 42, 57, 42, 5, 42, 4, - 4, 105, 7, 137, 138, 42, 22, 110, 139, 3, - 6, 32, 35, 36, 37, 38, 140, 141, 142, 144, - 145, 146, 147, 138, 143, 4, 4, 4, 148, 3, - 8, 4, 45, 43, 43, 4, 141, 42, 42 + 0, 42, 43, 44, 50, 51, 52, 53, 0, 5, + 7, 9, 45, 46, 47, 48, 56, 57, 58, 63, + 7, 68, 7, 54, 64, 59, 69, 55, 57, 65, + 66, 45, 61, 62, 10, 70, 71, 72, 11, 12, + 13, 14, 15, 22, 29, 32, 45, 67, 74, 75, + 76, 78, 79, 81, 83, 95, 112, 133, 6, 3, + 4, 8, 3, 73, 8, 77, 4, 80, 82, 113, + 4, 84, 134, 4, 3, 8, 57, 57, 45, 4, + 4, 46, 4, 4, 4, 7, 4, 4, 75, 4, + 7, 45, 58, 60, 45, 7, 96, 5, 5, 57, + 74, 16, 18, 19, 114, 115, 116, 119, 121, 23, + 24, 25, 67, 97, 98, 99, 101, 103, 7, 85, + 86, 87, 7, 135, 136, 8, 117, 120, 122, 3, + 8, 100, 102, 104, 3, 8, 88, 6, 3, 137, + 3, 6, 4, 4, 4, 115, 4, 4, 4, 98, + 30, 31, 67, 89, 90, 91, 93, 87, 33, 34, + 36, 37, 67, 79, 81, 138, 139, 140, 142, 143, + 145, 136, 17, 118, 45, 5, 7, 7, 7, 92, + 94, 3, 8, 141, 146, 4, 144, 3, 8, 7, + 123, 124, 125, 26, 27, 67, 79, 81, 105, 106, + 107, 109, 105, 105, 4, 4, 90, 4, 4, 46, + 4, 139, 126, 6, 3, 108, 110, 3, 8, 8, + 8, 45, 60, 45, 5, 45, 20, 21, 67, 79, + 81, 127, 128, 129, 131, 125, 4, 4, 106, 7, + 147, 148, 130, 132, 3, 8, 45, 28, 111, 149, + 3, 6, 4, 4, 128, 35, 38, 39, 40, 41, + 150, 151, 152, 154, 155, 156, 157, 148, 45, 45, + 153, 4, 4, 4, 158, 3, 8, 4, 48, 46, + 46, 4, 151, 45, 45 }; const unsigned char AgentParser::yyr1_[] = { - 0, 46, 48, 47, 49, 47, 50, 47, 52, 51, - 53, 54, 54, 54, 54, 54, 54, 54, 56, 55, - 57, 58, 58, 59, 59, 61, 60, 62, 62, 63, - 63, 64, 66, 65, 67, 68, 70, 69, 71, 71, - 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, - 74, 73, 75, 77, 76, 79, 78, 81, 80, 83, - 82, 84, 84, 85, 85, 87, 86, 88, 88, 88, - 89, 89, 91, 90, 93, 92, 95, 94, 96, 96, - 97, 97, 97, 97, 99, 98, 101, 100, 103, 102, - 104, 104, 105, 105, 105, 105, 105, 107, 106, 109, - 108, 110, 112, 111, 113, 113, 114, 114, 116, 115, - 117, 117, 118, 118, 118, 118, 118, 120, 119, 122, - 121, 124, 123, 125, 125, 127, 126, 128, 128, 129, - 129, 129, 129, 129, 129, 129, 131, 130, 132, 134, - 133, 136, 135, 137, 137, 139, 138, 140, 140, 141, - 141, 141, 141, 141, 143, 142, 144, 145, 146, 148, - 147 + 0, 49, 51, 50, 52, 50, 53, 50, 55, 54, + 56, 57, 57, 57, 57, 57, 57, 57, 59, 58, + 60, 61, 61, 62, 62, 64, 63, 65, 65, 66, + 66, 67, 69, 68, 70, 71, 73, 72, 74, 74, + 75, 75, 75, 75, 75, 75, 75, 75, 75, 77, + 76, 78, 80, 79, 82, 81, 84, 83, 85, 85, + 86, 86, 88, 87, 89, 89, 89, 90, 90, 92, + 91, 94, 93, 96, 95, 97, 97, 98, 98, 98, + 98, 100, 99, 102, 101, 104, 103, 105, 105, 106, + 106, 106, 106, 106, 108, 107, 110, 109, 111, 113, + 112, 114, 114, 115, 115, 115, 117, 116, 118, 120, + 119, 122, 121, 123, 123, 124, 124, 126, 125, 127, + 127, 128, 128, 128, 128, 128, 130, 129, 132, 131, + 134, 133, 135, 135, 137, 136, 138, 138, 139, 139, + 139, 139, 139, 139, 139, 141, 140, 142, 144, 143, + 146, 145, 147, 147, 149, 148, 150, 150, 151, 151, + 151, 151, 151, 153, 152, 154, 155, 156, 158, 157 }; const signed char @@ -2044,19 +2114,19 @@ namespace isc { namespace agent { 1, 1, 1, 1, 1, 1, 1, 1, 0, 4, 1, 0, 1, 3, 5, 0, 4, 0, 1, 1, 3, 2, 0, 4, 1, 1, 0, 6, 1, 3, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 4, 3, 0, 4, 0, 4, 0, 4, 0, - 6, 0, 1, 1, 3, 0, 4, 1, 3, 1, - 1, 1, 0, 4, 0, 4, 0, 6, 1, 3, - 1, 1, 1, 1, 0, 6, 0, 6, 0, 6, - 1, 3, 1, 1, 1, 1, 1, 0, 4, 0, - 4, 1, 0, 6, 0, 1, 1, 3, 0, 4, - 1, 3, 1, 1, 1, 1, 1, 0, 4, 0, - 4, 0, 6, 1, 3, 0, 4, 1, 3, 1, - 1, 1, 1, 1, 1, 1, 0, 4, 3, 0, - 4, 0, 6, 1, 3, 0, 4, 1, 3, 1, - 1, 1, 1, 1, 0, 4, 3, 3, 3, 0, - 4 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 4, 3, 0, 4, 0, 4, 0, 6, 0, 1, + 1, 3, 0, 4, 1, 3, 1, 1, 1, 0, + 4, 0, 4, 0, 6, 1, 3, 1, 1, 1, + 1, 0, 6, 0, 6, 0, 6, 1, 3, 1, + 1, 1, 1, 1, 0, 4, 0, 4, 1, 0, + 6, 1, 3, 1, 1, 1, 0, 4, 1, 0, + 4, 0, 6, 0, 1, 1, 3, 0, 4, 1, + 3, 1, 1, 1, 1, 1, 0, 4, 0, 4, + 0, 6, 1, 3, 0, 4, 1, 3, 1, 1, + 1, 1, 1, 1, 1, 0, 4, 3, 0, 4, + 0, 6, 1, 3, 0, 4, 1, 3, 1, 1, + 1, 1, 1, 0, 4, 3, 3, 3, 0, 4 }; @@ -2068,37 +2138,38 @@ namespace isc { namespace agent { { "\"end of file\"", "error", "\"invalid token\"", "\",\"", "\":\"", "\"[\"", "\"]\"", "\"{\"", "\"}\"", "\"null\"", "\"Control-agent\"", - "\"http-host\"", "\"http-port\"", "\"basic-authentication-realm\"", - "\"user-context\"", "\"comment\"", "\"control-sockets\"", "\"dhcp4\"", - "\"dhcp6\"", "\"d2\"", "\"socket-name\"", "\"socket-type\"", "\"unix\"", - "\"basic-authentications\"", "\"user\"", "\"password\"", - "\"hooks-libraries\"", "\"library\"", "\"parameters\"", "\"loggers\"", - "\"name\"", "\"output_options\"", "\"output\"", "\"debuglevel\"", - "\"severity\"", "\"flush\"", "\"maxsize\"", "\"maxver\"", "\"pattern\"", - "START_JSON", "START_AGENT", "START_SUB_AGENT", "\"constant string\"", - "\"integer\"", "\"floating point\"", "\"boolean\"", "$accept", "start", - "$@1", "$@2", "$@3", "sub_agent", "$@4", "json", "value", "map", "$@5", - "map_value", "map_content", "not_empty_map", "list_generic", "$@6", - "list_content", "not_empty_list", "unknown_map_entry", - "agent_syntax_map", "$@7", "global_objects", "global_object", - "agent_object", "$@8", "global_params", "global_param", "http_host", - "$@9", "http_port", "basic_authentication_realm", "$@10", "user_context", - "$@11", "comment", "$@12", "hooks_libraries", "$@13", + "\"http-host\"", "\"http-port\"", "\"user-context\"", "\"comment\"", + "\"authentication\"", "\"type\"", "\"basic\"", "\"realm\"", + "\"clients\"", "\"user\"", "\"password\"", "\"control-sockets\"", + "\"dhcp4\"", "\"dhcp6\"", "\"d2\"", "\"socket-name\"", "\"socket-type\"", + "\"unix\"", "\"hooks-libraries\"", "\"library\"", "\"parameters\"", + "\"loggers\"", "\"name\"", "\"output_options\"", "\"output\"", + "\"debuglevel\"", "\"severity\"", "\"flush\"", "\"maxsize\"", + "\"maxver\"", "\"pattern\"", "START_JSON", "START_AGENT", + "START_SUB_AGENT", "\"constant string\"", "\"integer\"", + "\"floating point\"", "\"boolean\"", "$accept", "start", "$@1", "$@2", + "$@3", "sub_agent", "$@4", "json", "value", "map", "$@5", "map_value", + "map_content", "not_empty_map", "list_generic", "$@6", "list_content", + "not_empty_list", "unknown_map_entry", "agent_syntax_map", "$@7", + "global_objects", "global_object", "agent_object", "$@8", + "global_params", "global_param", "http_host", "$@9", "http_port", + "user_context", "$@10", "comment", "$@11", "hooks_libraries", "$@12", "hooks_libraries_list", "not_empty_hooks_libraries_list", - "hooks_library", "$@14", "hooks_params", "hooks_param", "library", - "$@15", "parameters", "$@16", "control_sockets", "$@17", + "hooks_library", "$@13", "hooks_params", "hooks_param", "library", + "$@14", "parameters", "$@15", "control_sockets", "$@16", "control_sockets_params", "control_socket", "dhcp4_server_socket", - "$@18", "dhcp6_server_socket", "$@19", "d2_server_socket", "$@20", - "control_socket_params", "control_socket_param", "socket_name", "$@21", - "socket_type", "$@22", "socket_type_value", "basic_authentications", - "$@23", "basic_auth_list", "not_empty_basic_auth_list", "basic_auth", - "$@24", "basic_auth_params", "basic_auth_param", "user", "$@25", - "password", "$@26", "loggers", "$@27", "loggers_entries", "logger_entry", - "$@28", "logger_params", "logger_param", "name", "$@29", "debuglevel", - "severity", "$@30", "output_options_list", "$@31", - "output_options_list_content", "output_entry", "$@32", - "output_params_list", "output_params", "output", "$@33", "flush", - "maxsize", "maxver", "pattern", "$@34", YY_NULLPTR + "$@17", "dhcp6_server_socket", "$@18", "d2_server_socket", "$@19", + "control_socket_params", "control_socket_param", "socket_name", "$@20", + "socket_type", "$@21", "socket_type_value", "authentication", "$@22", + "auth_params", "auth_param", "auth_type", "$@23", "auth_type_value", + "realm", "$@24", "clients", "$@25", "clients_list", + "not_empty_clients_list", "basic_auth", "$@26", "clients_params", + "clients_param", "user", "$@27", "password", "$@28", "loggers", "$@29", + "loggers_entries", "logger_entry", "$@30", "logger_params", + "logger_param", "name", "$@31", "debuglevel", "severity", "$@32", + "output_options_list", "$@33", "output_options_list_content", + "output_entry", "$@34", "output_params_list", "output_params", "output", + "$@35", "flush", "maxsize", "maxver", "pattern", "$@36", YY_NULLPTR }; #endif @@ -2107,23 +2178,23 @@ namespace isc { namespace agent { const short AgentParser::yyrline_[] = { - 0, 115, 115, 115, 116, 116, 117, 117, 125, 125, - 136, 142, 143, 144, 145, 146, 147, 148, 152, 152, - 163, 168, 169, 177, 181, 188, 188, 194, 195, 198, - 202, 215, 223, 223, 235, 239, 243, 243, 260, 261, - 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, - 278, 278, 286, 291, 291, 299, 299, 324, 324, 352, - 352, 362, 363, 366, 367, 370, 370, 378, 379, 380, - 383, 384, 387, 387, 395, 395, 405, 405, 418, 419, - 424, 425, 426, 427, 431, 431, 442, 442, 453, 453, - 464, 465, 469, 470, 471, 472, 473, 477, 477, 486, - 486, 494, 501, 501, 511, 512, 515, 516, 519, 519, - 527, 528, 531, 532, 533, 534, 535, 538, 538, 546, - 546, 558, 558, 570, 571, 575, 575, 583, 584, 587, - 588, 589, 590, 591, 592, 593, 596, 596, 604, 609, - 609, 617, 617, 627, 628, 631, 631, 639, 640, 643, - 644, 645, 646, 647, 650, 650, 658, 663, 668, 673, - 673 + 0, 119, 119, 119, 120, 120, 121, 121, 129, 129, + 140, 146, 147, 148, 149, 150, 151, 152, 156, 156, + 167, 172, 173, 181, 185, 192, 192, 198, 199, 202, + 206, 219, 227, 227, 239, 243, 247, 247, 264, 265, + 270, 271, 272, 273, 274, 275, 276, 277, 278, 281, + 281, 289, 294, 294, 319, 319, 347, 347, 357, 358, + 361, 362, 365, 365, 373, 374, 375, 378, 379, 382, + 382, 390, 390, 400, 400, 413, 414, 419, 420, 421, + 422, 426, 426, 437, 437, 448, 448, 459, 460, 464, + 465, 466, 467, 468, 472, 472, 481, 481, 489, 496, + 496, 509, 510, 513, 514, 515, 518, 518, 526, 529, + 529, 538, 538, 549, 550, 553, 554, 557, 557, 565, + 566, 569, 570, 571, 572, 573, 576, 576, 584, 584, + 596, 596, 608, 609, 613, 613, 621, 622, 625, 626, + 627, 628, 629, 630, 631, 634, 634, 642, 647, 647, + 655, 655, 665, 666, 669, 669, 677, 678, 681, 682, + 683, 684, 685, 688, 688, 696, 701, 706, 711, 711 }; void @@ -2156,9 +2227,9 @@ namespace isc { namespace agent { #line 14 "agent_parser.yy" } } // isc::agent -#line 2160 "agent_parser.cc" +#line 2231 "agent_parser.cc" -#line 681 "agent_parser.yy" +#line 719 "agent_parser.yy" void diff --git a/src/bin/agent/agent_parser.h b/src/bin/agent/agent_parser.h index 0668130a64..074d7fa5d5 100644 --- a/src/bin/agent/agent_parser.h +++ b/src/bin/agent/agent_parser.h @@ -416,6 +416,7 @@ namespace isc { namespace agent { // value // map_value // socket_type_value + // auth_type_value char dummy1[sizeof (ElementPtr)]; // "boolean" @@ -490,39 +491,42 @@ namespace isc { namespace agent { TOKEN_CONTROL_AGENT = 265, // "Control-agent" TOKEN_HTTP_HOST = 266, // "http-host" TOKEN_HTTP_PORT = 267, // "http-port" - TOKEN_BASIC_AUTHENTICATION_REALM = 268, // "basic-authentication-realm" - TOKEN_USER_CONTEXT = 269, // "user-context" - TOKEN_COMMENT = 270, // "comment" - TOKEN_CONTROL_SOCKETS = 271, // "control-sockets" - TOKEN_DHCP4_SERVER = 272, // "dhcp4" - TOKEN_DHCP6_SERVER = 273, // "dhcp6" - TOKEN_D2_SERVER = 274, // "d2" - TOKEN_SOCKET_NAME = 275, // "socket-name" - TOKEN_SOCKET_TYPE = 276, // "socket-type" - TOKEN_UNIX = 277, // "unix" - TOKEN_BASIC_AUTHENTICATIONS = 278, // "basic-authentications" - TOKEN_USER = 279, // "user" - TOKEN_PASSWORD = 280, // "password" - TOKEN_HOOKS_LIBRARIES = 281, // "hooks-libraries" - TOKEN_LIBRARY = 282, // "library" - TOKEN_PARAMETERS = 283, // "parameters" - TOKEN_LOGGERS = 284, // "loggers" - TOKEN_NAME = 285, // "name" - TOKEN_OUTPUT_OPTIONS = 286, // "output_options" - TOKEN_OUTPUT = 287, // "output" - TOKEN_DEBUGLEVEL = 288, // "debuglevel" - TOKEN_SEVERITY = 289, // "severity" - TOKEN_FLUSH = 290, // "flush" - TOKEN_MAXSIZE = 291, // "maxsize" - TOKEN_MAXVER = 292, // "maxver" - TOKEN_PATTERN = 293, // "pattern" - TOKEN_START_JSON = 294, // START_JSON - TOKEN_START_AGENT = 295, // START_AGENT - TOKEN_START_SUB_AGENT = 296, // START_SUB_AGENT - TOKEN_STRING = 297, // "constant string" - TOKEN_INTEGER = 298, // "integer" - TOKEN_FLOAT = 299, // "floating point" - TOKEN_BOOLEAN = 300 // "boolean" + TOKEN_USER_CONTEXT = 268, // "user-context" + TOKEN_COMMENT = 269, // "comment" + TOKEN_AUTHENTICATION = 270, // "authentication" + TOKEN_TYPE = 271, // "type" + TOKEN_BASIC = 272, // "basic" + TOKEN_REALM = 273, // "realm" + TOKEN_CLIENTS = 274, // "clients" + TOKEN_USER = 275, // "user" + TOKEN_PASSWORD = 276, // "password" + TOKEN_CONTROL_SOCKETS = 277, // "control-sockets" + TOKEN_DHCP4_SERVER = 278, // "dhcp4" + TOKEN_DHCP6_SERVER = 279, // "dhcp6" + TOKEN_D2_SERVER = 280, // "d2" + TOKEN_SOCKET_NAME = 281, // "socket-name" + TOKEN_SOCKET_TYPE = 282, // "socket-type" + TOKEN_UNIX = 283, // "unix" + TOKEN_HOOKS_LIBRARIES = 284, // "hooks-libraries" + TOKEN_LIBRARY = 285, // "library" + TOKEN_PARAMETERS = 286, // "parameters" + TOKEN_LOGGERS = 287, // "loggers" + TOKEN_NAME = 288, // "name" + TOKEN_OUTPUT_OPTIONS = 289, // "output_options" + TOKEN_OUTPUT = 290, // "output" + TOKEN_DEBUGLEVEL = 291, // "debuglevel" + TOKEN_SEVERITY = 292, // "severity" + TOKEN_FLUSH = 293, // "flush" + TOKEN_MAXSIZE = 294, // "maxsize" + TOKEN_MAXVER = 295, // "maxver" + TOKEN_PATTERN = 296, // "pattern" + TOKEN_START_JSON = 297, // START_JSON + TOKEN_START_AGENT = 298, // START_AGENT + TOKEN_START_SUB_AGENT = 299, // START_SUB_AGENT + TOKEN_STRING = 300, // "constant string" + TOKEN_INTEGER = 301, // "integer" + TOKEN_FLOAT = 302, // "floating point" + TOKEN_BOOLEAN = 303 // "boolean" }; /// Backward compatibility alias (Bison 3.6). typedef token_kind_type yytokentype; @@ -539,7 +543,7 @@ namespace isc { namespace agent { { enum symbol_kind_type { - YYNTOKENS = 46, ///< Number of tokens. + YYNTOKENS = 49, ///< Number of tokens. S_YYEMPTY = -2, S_YYEOF = 0, // "end of file" S_YYerror = 1, // error @@ -554,142 +558,152 @@ namespace isc { namespace agent { S_CONTROL_AGENT = 10, // "Control-agent" S_HTTP_HOST = 11, // "http-host" S_HTTP_PORT = 12, // "http-port" - S_BASIC_AUTHENTICATION_REALM = 13, // "basic-authentication-realm" - S_USER_CONTEXT = 14, // "user-context" - S_COMMENT = 15, // "comment" - S_CONTROL_SOCKETS = 16, // "control-sockets" - S_DHCP4_SERVER = 17, // "dhcp4" - S_DHCP6_SERVER = 18, // "dhcp6" - S_D2_SERVER = 19, // "d2" - S_SOCKET_NAME = 20, // "socket-name" - S_SOCKET_TYPE = 21, // "socket-type" - S_UNIX = 22, // "unix" - S_BASIC_AUTHENTICATIONS = 23, // "basic-authentications" - S_USER = 24, // "user" - S_PASSWORD = 25, // "password" - S_HOOKS_LIBRARIES = 26, // "hooks-libraries" - S_LIBRARY = 27, // "library" - S_PARAMETERS = 28, // "parameters" - S_LOGGERS = 29, // "loggers" - S_NAME = 30, // "name" - S_OUTPUT_OPTIONS = 31, // "output_options" - S_OUTPUT = 32, // "output" - S_DEBUGLEVEL = 33, // "debuglevel" - S_SEVERITY = 34, // "severity" - S_FLUSH = 35, // "flush" - S_MAXSIZE = 36, // "maxsize" - S_MAXVER = 37, // "maxver" - S_PATTERN = 38, // "pattern" - S_START_JSON = 39, // START_JSON - S_START_AGENT = 40, // START_AGENT - S_START_SUB_AGENT = 41, // START_SUB_AGENT - S_STRING = 42, // "constant string" - S_INTEGER = 43, // "integer" - S_FLOAT = 44, // "floating point" - S_BOOLEAN = 45, // "boolean" - S_YYACCEPT = 46, // $accept - S_start = 47, // start - S_48_1 = 48, // $@1 - S_49_2 = 49, // $@2 - S_50_3 = 50, // $@3 - S_sub_agent = 51, // sub_agent - S_52_4 = 52, // $@4 - S_json = 53, // json - S_value = 54, // value - S_map = 55, // map - S_56_5 = 56, // $@5 - S_map_value = 57, // map_value - S_map_content = 58, // map_content - S_not_empty_map = 59, // not_empty_map - S_list_generic = 60, // list_generic - S_61_6 = 61, // $@6 - S_list_content = 62, // list_content - S_not_empty_list = 63, // not_empty_list - S_unknown_map_entry = 64, // unknown_map_entry - S_agent_syntax_map = 65, // agent_syntax_map - S_66_7 = 66, // $@7 - S_global_objects = 67, // global_objects - S_global_object = 68, // global_object - S_agent_object = 69, // agent_object - S_70_8 = 70, // $@8 - S_global_params = 71, // global_params - S_global_param = 72, // global_param - S_http_host = 73, // http_host - S_74_9 = 74, // $@9 - S_http_port = 75, // http_port - S_basic_authentication_realm = 76, // basic_authentication_realm - S_77_10 = 77, // $@10 - S_user_context = 78, // user_context - S_79_11 = 79, // $@11 - S_comment = 80, // comment - S_81_12 = 81, // $@12 - S_hooks_libraries = 82, // hooks_libraries - S_83_13 = 83, // $@13 - S_hooks_libraries_list = 84, // hooks_libraries_list - S_not_empty_hooks_libraries_list = 85, // not_empty_hooks_libraries_list - S_hooks_library = 86, // hooks_library - S_87_14 = 87, // $@14 - S_hooks_params = 88, // hooks_params - S_hooks_param = 89, // hooks_param - S_library = 90, // library - S_91_15 = 91, // $@15 - S_parameters = 92, // parameters - S_93_16 = 93, // $@16 - S_control_sockets = 94, // control_sockets - S_95_17 = 95, // $@17 - S_control_sockets_params = 96, // control_sockets_params - S_control_socket = 97, // control_socket - S_dhcp4_server_socket = 98, // dhcp4_server_socket - S_99_18 = 99, // $@18 - S_dhcp6_server_socket = 100, // dhcp6_server_socket - S_101_19 = 101, // $@19 - S_d2_server_socket = 102, // d2_server_socket - S_103_20 = 103, // $@20 - S_control_socket_params = 104, // control_socket_params - S_control_socket_param = 105, // control_socket_param - S_socket_name = 106, // socket_name - S_107_21 = 107, // $@21 - S_socket_type = 108, // socket_type - S_109_22 = 109, // $@22 - S_socket_type_value = 110, // socket_type_value - S_basic_authentications = 111, // basic_authentications - S_112_23 = 112, // $@23 - S_basic_auth_list = 113, // basic_auth_list - S_not_empty_basic_auth_list = 114, // not_empty_basic_auth_list - S_basic_auth = 115, // basic_auth - S_116_24 = 116, // $@24 - S_basic_auth_params = 117, // basic_auth_params - S_basic_auth_param = 118, // basic_auth_param - S_user = 119, // user - S_120_25 = 120, // $@25 - S_password = 121, // password - S_122_26 = 122, // $@26 - S_loggers = 123, // loggers - S_124_27 = 124, // $@27 - S_loggers_entries = 125, // loggers_entries - S_logger_entry = 126, // logger_entry - S_127_28 = 127, // $@28 - S_logger_params = 128, // logger_params - S_logger_param = 129, // logger_param - S_name = 130, // name - S_131_29 = 131, // $@29 - S_debuglevel = 132, // debuglevel - S_severity = 133, // severity - S_134_30 = 134, // $@30 - S_output_options_list = 135, // output_options_list - S_136_31 = 136, // $@31 - S_output_options_list_content = 137, // output_options_list_content - S_output_entry = 138, // output_entry - S_139_32 = 139, // $@32 - S_output_params_list = 140, // output_params_list - S_output_params = 141, // output_params - S_output = 142, // output - S_143_33 = 143, // $@33 - S_flush = 144, // flush - S_maxsize = 145, // maxsize - S_maxver = 146, // maxver - S_pattern = 147, // pattern - S_148_34 = 148 // $@34 + S_USER_CONTEXT = 13, // "user-context" + S_COMMENT = 14, // "comment" + S_AUTHENTICATION = 15, // "authentication" + S_TYPE = 16, // "type" + S_BASIC = 17, // "basic" + S_REALM = 18, // "realm" + S_CLIENTS = 19, // "clients" + S_USER = 20, // "user" + S_PASSWORD = 21, // "password" + S_CONTROL_SOCKETS = 22, // "control-sockets" + S_DHCP4_SERVER = 23, // "dhcp4" + S_DHCP6_SERVER = 24, // "dhcp6" + S_D2_SERVER = 25, // "d2" + S_SOCKET_NAME = 26, // "socket-name" + S_SOCKET_TYPE = 27, // "socket-type" + S_UNIX = 28, // "unix" + S_HOOKS_LIBRARIES = 29, // "hooks-libraries" + S_LIBRARY = 30, // "library" + S_PARAMETERS = 31, // "parameters" + S_LOGGERS = 32, // "loggers" + S_NAME = 33, // "name" + S_OUTPUT_OPTIONS = 34, // "output_options" + S_OUTPUT = 35, // "output" + S_DEBUGLEVEL = 36, // "debuglevel" + S_SEVERITY = 37, // "severity" + S_FLUSH = 38, // "flush" + S_MAXSIZE = 39, // "maxsize" + S_MAXVER = 40, // "maxver" + S_PATTERN = 41, // "pattern" + S_START_JSON = 42, // START_JSON + S_START_AGENT = 43, // START_AGENT + S_START_SUB_AGENT = 44, // START_SUB_AGENT + S_STRING = 45, // "constant string" + S_INTEGER = 46, // "integer" + S_FLOAT = 47, // "floating point" + S_BOOLEAN = 48, // "boolean" + S_YYACCEPT = 49, // $accept + S_start = 50, // start + S_51_1 = 51, // $@1 + S_52_2 = 52, // $@2 + S_53_3 = 53, // $@3 + S_sub_agent = 54, // sub_agent + S_55_4 = 55, // $@4 + S_json = 56, // json + S_value = 57, // value + S_map = 58, // map + S_59_5 = 59, // $@5 + S_map_value = 60, // map_value + S_map_content = 61, // map_content + S_not_empty_map = 62, // not_empty_map + S_list_generic = 63, // list_generic + S_64_6 = 64, // $@6 + S_list_content = 65, // list_content + S_not_empty_list = 66, // not_empty_list + S_unknown_map_entry = 67, // unknown_map_entry + S_agent_syntax_map = 68, // agent_syntax_map + S_69_7 = 69, // $@7 + S_global_objects = 70, // global_objects + S_global_object = 71, // global_object + S_agent_object = 72, // agent_object + S_73_8 = 73, // $@8 + S_global_params = 74, // global_params + S_global_param = 75, // global_param + S_http_host = 76, // http_host + S_77_9 = 77, // $@9 + S_http_port = 78, // http_port + S_user_context = 79, // user_context + S_80_10 = 80, // $@10 + S_comment = 81, // comment + S_82_11 = 82, // $@11 + S_hooks_libraries = 83, // hooks_libraries + S_84_12 = 84, // $@12 + S_hooks_libraries_list = 85, // hooks_libraries_list + S_not_empty_hooks_libraries_list = 86, // not_empty_hooks_libraries_list + S_hooks_library = 87, // hooks_library + S_88_13 = 88, // $@13 + S_hooks_params = 89, // hooks_params + S_hooks_param = 90, // hooks_param + S_library = 91, // library + S_92_14 = 92, // $@14 + S_parameters = 93, // parameters + S_94_15 = 94, // $@15 + S_control_sockets = 95, // control_sockets + S_96_16 = 96, // $@16 + S_control_sockets_params = 97, // control_sockets_params + S_control_socket = 98, // control_socket + S_dhcp4_server_socket = 99, // dhcp4_server_socket + S_100_17 = 100, // $@17 + S_dhcp6_server_socket = 101, // dhcp6_server_socket + S_102_18 = 102, // $@18 + S_d2_server_socket = 103, // d2_server_socket + S_104_19 = 104, // $@19 + S_control_socket_params = 105, // control_socket_params + S_control_socket_param = 106, // control_socket_param + S_socket_name = 107, // socket_name + S_108_20 = 108, // $@20 + S_socket_type = 109, // socket_type + S_110_21 = 110, // $@21 + S_socket_type_value = 111, // socket_type_value + S_authentication = 112, // authentication + S_113_22 = 113, // $@22 + S_auth_params = 114, // auth_params + S_auth_param = 115, // auth_param + S_auth_type = 116, // auth_type + S_117_23 = 117, // $@23 + S_auth_type_value = 118, // auth_type_value + S_realm = 119, // realm + S_120_24 = 120, // $@24 + S_clients = 121, // clients + S_122_25 = 122, // $@25 + S_clients_list = 123, // clients_list + S_not_empty_clients_list = 124, // not_empty_clients_list + S_basic_auth = 125, // basic_auth + S_126_26 = 126, // $@26 + S_clients_params = 127, // clients_params + S_clients_param = 128, // clients_param + S_user = 129, // user + S_130_27 = 130, // $@27 + S_password = 131, // password + S_132_28 = 132, // $@28 + S_loggers = 133, // loggers + S_134_29 = 134, // $@29 + S_loggers_entries = 135, // loggers_entries + S_logger_entry = 136, // logger_entry + S_137_30 = 137, // $@30 + S_logger_params = 138, // logger_params + S_logger_param = 139, // logger_param + S_name = 140, // name + S_141_31 = 141, // $@31 + S_debuglevel = 142, // debuglevel + S_severity = 143, // severity + S_144_32 = 144, // $@32 + S_output_options_list = 145, // output_options_list + S_146_33 = 146, // $@33 + S_output_options_list_content = 147, // output_options_list_content + S_output_entry = 148, // output_entry + S_149_34 = 149, // $@34 + S_output_params_list = 150, // output_params_list + S_output_params = 151, // output_params + S_output = 152, // output + S_153_35 = 153, // $@35 + S_flush = 154, // flush + S_maxsize = 155, // maxsize + S_maxver = 156, // maxver + S_pattern = 157, // pattern + S_158_36 = 158 // $@36 }; }; @@ -729,6 +743,7 @@ namespace isc { namespace agent { case symbol_kind::S_value: // value case symbol_kind::S_map_value: // map_value case symbol_kind::S_socket_type_value: // socket_type_value + case symbol_kind::S_auth_type_value: // auth_type_value value.move< ElementPtr > (std::move (that.value)); break; @@ -861,6 +876,7 @@ switch (yykind) case symbol_kind::S_value: // value case symbol_kind::S_map_value: // map_value case symbol_kind::S_socket_type_value: // socket_type_value + case symbol_kind::S_auth_type_value: // auth_type_value value.template destroy< ElementPtr > (); break; @@ -970,13 +986,13 @@ switch (yykind) symbol_type (int tok, location_type l) : super_type(token_type (tok), std::move (l)) { - YY_ASSERT (tok == token::TOKEN_END || tok == token::TOKEN_AGENT_error || tok == token::TOKEN_AGENT_UNDEF || tok == token::TOKEN_COMMA || tok == token::TOKEN_COLON || tok == token::TOKEN_LSQUARE_BRACKET || tok == token::TOKEN_RSQUARE_BRACKET || tok == token::TOKEN_LCURLY_BRACKET || tok == token::TOKEN_RCURLY_BRACKET || tok == token::TOKEN_NULL_TYPE || tok == token::TOKEN_CONTROL_AGENT || tok == token::TOKEN_HTTP_HOST || tok == token::TOKEN_HTTP_PORT || tok == token::TOKEN_BASIC_AUTHENTICATION_REALM || tok == token::TOKEN_USER_CONTEXT || tok == token::TOKEN_COMMENT || tok == token::TOKEN_CONTROL_SOCKETS || tok == token::TOKEN_DHCP4_SERVER || tok == token::TOKEN_DHCP6_SERVER || tok == token::TOKEN_D2_SERVER || tok == token::TOKEN_SOCKET_NAME || tok == token::TOKEN_SOCKET_TYPE || tok == token::TOKEN_UNIX || tok == token::TOKEN_BASIC_AUTHENTICATIONS || tok == token::TOKEN_USER || tok == token::TOKEN_PASSWORD || tok == token::TOKEN_HOOKS_LIBRARIES || tok == token::TOKEN_LIBRARY || tok == token::TOKEN_PARAMETERS || tok == token::TOKEN_LOGGERS || tok == token::TOKEN_NAME || tok == token::TOKEN_OUTPUT_OPTIONS || tok == token::TOKEN_OUTPUT || tok == token::TOKEN_DEBUGLEVEL || tok == token::TOKEN_SEVERITY || tok == token::TOKEN_FLUSH || tok == token::TOKEN_MAXSIZE || tok == token::TOKEN_MAXVER || tok == token::TOKEN_PATTERN || tok == token::TOKEN_START_JSON || tok == token::TOKEN_START_AGENT || tok == token::TOKEN_START_SUB_AGENT); + YY_ASSERT (tok == token::TOKEN_END || tok == token::TOKEN_AGENT_error || tok == token::TOKEN_AGENT_UNDEF || tok == token::TOKEN_COMMA || tok == token::TOKEN_COLON || tok == token::TOKEN_LSQUARE_BRACKET || tok == token::TOKEN_RSQUARE_BRACKET || tok == token::TOKEN_LCURLY_BRACKET || tok == token::TOKEN_RCURLY_BRACKET || tok == token::TOKEN_NULL_TYPE || tok == token::TOKEN_CONTROL_AGENT || tok == token::TOKEN_HTTP_HOST || tok == token::TOKEN_HTTP_PORT || tok == token::TOKEN_USER_CONTEXT || tok == token::TOKEN_COMMENT || tok == token::TOKEN_AUTHENTICATION || tok == token::TOKEN_TYPE || tok == token::TOKEN_BASIC || tok == token::TOKEN_REALM || tok == token::TOKEN_CLIENTS || tok == token::TOKEN_USER || tok == token::TOKEN_PASSWORD || tok == token::TOKEN_CONTROL_SOCKETS || tok == token::TOKEN_DHCP4_SERVER || tok == token::TOKEN_DHCP6_SERVER || tok == token::TOKEN_D2_SERVER || tok == token::TOKEN_SOCKET_NAME || tok == token::TOKEN_SOCKET_TYPE || tok == token::TOKEN_UNIX || tok == token::TOKEN_HOOKS_LIBRARIES || tok == token::TOKEN_LIBRARY || tok == token::TOKEN_PARAMETERS || tok == token::TOKEN_LOGGERS || tok == token::TOKEN_NAME || tok == token::TOKEN_OUTPUT_OPTIONS || tok == token::TOKEN_OUTPUT || tok == token::TOKEN_DEBUGLEVEL || tok == token::TOKEN_SEVERITY || tok == token::TOKEN_FLUSH || tok == token::TOKEN_MAXSIZE || tok == token::TOKEN_MAXVER || tok == token::TOKEN_PATTERN || tok == token::TOKEN_START_JSON || tok == token::TOKEN_START_AGENT || tok == token::TOKEN_START_SUB_AGENT); } #else symbol_type (int tok, const location_type& l) : super_type(token_type (tok), l) { - YY_ASSERT (tok == token::TOKEN_END || tok == token::TOKEN_AGENT_error || tok == token::TOKEN_AGENT_UNDEF || tok == token::TOKEN_COMMA || tok == token::TOKEN_COLON || tok == token::TOKEN_LSQUARE_BRACKET || tok == token::TOKEN_RSQUARE_BRACKET || tok == token::TOKEN_LCURLY_BRACKET || tok == token::TOKEN_RCURLY_BRACKET || tok == token::TOKEN_NULL_TYPE || tok == token::TOKEN_CONTROL_AGENT || tok == token::TOKEN_HTTP_HOST || tok == token::TOKEN_HTTP_PORT || tok == token::TOKEN_BASIC_AUTHENTICATION_REALM || tok == token::TOKEN_USER_CONTEXT || tok == token::TOKEN_COMMENT || tok == token::TOKEN_CONTROL_SOCKETS || tok == token::TOKEN_DHCP4_SERVER || tok == token::TOKEN_DHCP6_SERVER || tok == token::TOKEN_D2_SERVER || tok == token::TOKEN_SOCKET_NAME || tok == token::TOKEN_SOCKET_TYPE || tok == token::TOKEN_UNIX || tok == token::TOKEN_BASIC_AUTHENTICATIONS || tok == token::TOKEN_USER || tok == token::TOKEN_PASSWORD || tok == token::TOKEN_HOOKS_LIBRARIES || tok == token::TOKEN_LIBRARY || tok == token::TOKEN_PARAMETERS || tok == token::TOKEN_LOGGERS || tok == token::TOKEN_NAME || tok == token::TOKEN_OUTPUT_OPTIONS || tok == token::TOKEN_OUTPUT || tok == token::TOKEN_DEBUGLEVEL || tok == token::TOKEN_SEVERITY || tok == token::TOKEN_FLUSH || tok == token::TOKEN_MAXSIZE || tok == token::TOKEN_MAXVER || tok == token::TOKEN_PATTERN || tok == token::TOKEN_START_JSON || tok == token::TOKEN_START_AGENT || tok == token::TOKEN_START_SUB_AGENT); + YY_ASSERT (tok == token::TOKEN_END || tok == token::TOKEN_AGENT_error || tok == token::TOKEN_AGENT_UNDEF || tok == token::TOKEN_COMMA || tok == token::TOKEN_COLON || tok == token::TOKEN_LSQUARE_BRACKET || tok == token::TOKEN_RSQUARE_BRACKET || tok == token::TOKEN_LCURLY_BRACKET || tok == token::TOKEN_RCURLY_BRACKET || tok == token::TOKEN_NULL_TYPE || tok == token::TOKEN_CONTROL_AGENT || tok == token::TOKEN_HTTP_HOST || tok == token::TOKEN_HTTP_PORT || tok == token::TOKEN_USER_CONTEXT || tok == token::TOKEN_COMMENT || tok == token::TOKEN_AUTHENTICATION || tok == token::TOKEN_TYPE || tok == token::TOKEN_BASIC || tok == token::TOKEN_REALM || tok == token::TOKEN_CLIENTS || tok == token::TOKEN_USER || tok == token::TOKEN_PASSWORD || tok == token::TOKEN_CONTROL_SOCKETS || tok == token::TOKEN_DHCP4_SERVER || tok == token::TOKEN_DHCP6_SERVER || tok == token::TOKEN_D2_SERVER || tok == token::TOKEN_SOCKET_NAME || tok == token::TOKEN_SOCKET_TYPE || tok == token::TOKEN_UNIX || tok == token::TOKEN_HOOKS_LIBRARIES || tok == token::TOKEN_LIBRARY || tok == token::TOKEN_PARAMETERS || tok == token::TOKEN_LOGGERS || tok == token::TOKEN_NAME || tok == token::TOKEN_OUTPUT_OPTIONS || tok == token::TOKEN_OUTPUT || tok == token::TOKEN_DEBUGLEVEL || tok == token::TOKEN_SEVERITY || tok == token::TOKEN_FLUSH || tok == token::TOKEN_MAXSIZE || tok == token::TOKEN_MAXVER || tok == token::TOKEN_PATTERN || tok == token::TOKEN_START_JSON || tok == token::TOKEN_START_AGENT || tok == token::TOKEN_START_SUB_AGENT); } #endif #if 201103L <= YY_CPLUSPLUS @@ -1277,196 +1293,241 @@ switch (yykind) #if 201103L <= YY_CPLUSPLUS static symbol_type - make_BASIC_AUTHENTICATION_REALM (location_type l) + make_USER_CONTEXT (location_type l) { - return symbol_type (token::TOKEN_BASIC_AUTHENTICATION_REALM, std::move (l)); + return symbol_type (token::TOKEN_USER_CONTEXT, std::move (l)); } #else static symbol_type - make_BASIC_AUTHENTICATION_REALM (const location_type& l) + make_USER_CONTEXT (const location_type& l) { - return symbol_type (token::TOKEN_BASIC_AUTHENTICATION_REALM, l); + return symbol_type (token::TOKEN_USER_CONTEXT, l); } #endif #if 201103L <= YY_CPLUSPLUS static symbol_type - make_USER_CONTEXT (location_type l) + make_COMMENT (location_type l) { - return symbol_type (token::TOKEN_USER_CONTEXT, std::move (l)); + return symbol_type (token::TOKEN_COMMENT, std::move (l)); } #else static symbol_type - make_USER_CONTEXT (const location_type& l) + make_COMMENT (const location_type& l) { - return symbol_type (token::TOKEN_USER_CONTEXT, l); + return symbol_type (token::TOKEN_COMMENT, l); } #endif #if 201103L <= YY_CPLUSPLUS static symbol_type - make_COMMENT (location_type l) + make_AUTHENTICATION (location_type l) { - return symbol_type (token::TOKEN_COMMENT, std::move (l)); + return symbol_type (token::TOKEN_AUTHENTICATION, std::move (l)); } #else static symbol_type - make_COMMENT (const location_type& l) + make_AUTHENTICATION (const location_type& l) { - return symbol_type (token::TOKEN_COMMENT, l); + return symbol_type (token::TOKEN_AUTHENTICATION, l); } #endif #if 201103L <= YY_CPLUSPLUS static symbol_type - make_CONTROL_SOCKETS (location_type l) + make_TYPE (location_type l) { - return symbol_type (token::TOKEN_CONTROL_SOCKETS, std::move (l)); + return symbol_type (token::TOKEN_TYPE, std::move (l)); } #else static symbol_type - make_CONTROL_SOCKETS (const location_type& l) + make_TYPE (const location_type& l) { - return symbol_type (token::TOKEN_CONTROL_SOCKETS, l); + return symbol_type (token::TOKEN_TYPE, l); } #endif #if 201103L <= YY_CPLUSPLUS static symbol_type - make_DHCP4_SERVER (location_type l) + make_BASIC (location_type l) { - return symbol_type (token::TOKEN_DHCP4_SERVER, std::move (l)); + return symbol_type (token::TOKEN_BASIC, std::move (l)); } #else static symbol_type - make_DHCP4_SERVER (const location_type& l) + make_BASIC (const location_type& l) { - return symbol_type (token::TOKEN_DHCP4_SERVER, l); + return symbol_type (token::TOKEN_BASIC, l); } #endif #if 201103L <= YY_CPLUSPLUS static symbol_type - make_DHCP6_SERVER (location_type l) + make_REALM (location_type l) { - return symbol_type (token::TOKEN_DHCP6_SERVER, std::move (l)); + return symbol_type (token::TOKEN_REALM, std::move (l)); } #else static symbol_type - make_DHCP6_SERVER (const location_type& l) + make_REALM (const location_type& l) { - return symbol_type (token::TOKEN_DHCP6_SERVER, l); + return symbol_type (token::TOKEN_REALM, l); } #endif #if 201103L <= YY_CPLUSPLUS static symbol_type - make_D2_SERVER (location_type l) + make_CLIENTS (location_type l) { - return symbol_type (token::TOKEN_D2_SERVER, std::move (l)); + return symbol_type (token::TOKEN_CLIENTS, std::move (l)); } #else static symbol_type - make_D2_SERVER (const location_type& l) + make_CLIENTS (const location_type& l) { - return symbol_type (token::TOKEN_D2_SERVER, l); + return symbol_type (token::TOKEN_CLIENTS, l); } #endif #if 201103L <= YY_CPLUSPLUS static symbol_type - make_SOCKET_NAME (location_type l) + make_USER (location_type l) { - return symbol_type (token::TOKEN_SOCKET_NAME, std::move (l)); + return symbol_type (token::TOKEN_USER, std::move (l)); } #else static symbol_type - make_SOCKET_NAME (const location_type& l) + make_USER (const location_type& l) { - return symbol_type (token::TOKEN_SOCKET_NAME, l); + return symbol_type (token::TOKEN_USER, l); } #endif #if 201103L <= YY_CPLUSPLUS static symbol_type - make_SOCKET_TYPE (location_type l) + make_PASSWORD (location_type l) { - return symbol_type (token::TOKEN_SOCKET_TYPE, std::move (l)); + return symbol_type (token::TOKEN_PASSWORD, std::move (l)); } #else static symbol_type - make_SOCKET_TYPE (const location_type& l) + make_PASSWORD (const location_type& l) { - return symbol_type (token::TOKEN_SOCKET_TYPE, l); + return symbol_type (token::TOKEN_PASSWORD, l); } #endif #if 201103L <= YY_CPLUSPLUS static symbol_type - make_UNIX (location_type l) + make_CONTROL_SOCKETS (location_type l) { - return symbol_type (token::TOKEN_UNIX, std::move (l)); + return symbol_type (token::TOKEN_CONTROL_SOCKETS, std::move (l)); } #else static symbol_type - make_UNIX (const location_type& l) + make_CONTROL_SOCKETS (const location_type& l) { - return symbol_type (token::TOKEN_UNIX, l); + return symbol_type (token::TOKEN_CONTROL_SOCKETS, l); } #endif #if 201103L <= YY_CPLUSPLUS static symbol_type - make_BASIC_AUTHENTICATIONS (location_type l) + make_DHCP4_SERVER (location_type l) { - return symbol_type (token::TOKEN_BASIC_AUTHENTICATIONS, std::move (l)); + return symbol_type (token::TOKEN_DHCP4_SERVER, std::move (l)); } #else static symbol_type - make_BASIC_AUTHENTICATIONS (const location_type& l) + make_DHCP4_SERVER (const location_type& l) { - return symbol_type (token::TOKEN_BASIC_AUTHENTICATIONS, l); + return symbol_type (token::TOKEN_DHCP4_SERVER, l); } #endif #if 201103L <= YY_CPLUSPLUS static symbol_type - make_USER (location_type l) + make_DHCP6_SERVER (location_type l) { - return symbol_type (token::TOKEN_USER, std::move (l)); + return symbol_type (token::TOKEN_DHCP6_SERVER, std::move (l)); } #else static symbol_type - make_USER (const location_type& l) + make_DHCP6_SERVER (const location_type& l) { - return symbol_type (token::TOKEN_USER, l); + return symbol_type (token::TOKEN_DHCP6_SERVER, l); } #endif #if 201103L <= YY_CPLUSPLUS static symbol_type - make_PASSWORD (location_type l) + make_D2_SERVER (location_type l) { - return symbol_type (token::TOKEN_PASSWORD, std::move (l)); + return symbol_type (token::TOKEN_D2_SERVER, std::move (l)); } #else static symbol_type - make_PASSWORD (const location_type& l) + make_D2_SERVER (const location_type& l) { - return symbol_type (token::TOKEN_PASSWORD, l); + return symbol_type (token::TOKEN_D2_SERVER, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SOCKET_NAME (location_type l) + { + return symbol_type (token::TOKEN_SOCKET_NAME, std::move (l)); + } +#else + static + symbol_type + make_SOCKET_NAME (const location_type& l) + { + return symbol_type (token::TOKEN_SOCKET_NAME, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_SOCKET_TYPE (location_type l) + { + return symbol_type (token::TOKEN_SOCKET_TYPE, std::move (l)); + } +#else + static + symbol_type + make_SOCKET_TYPE (const location_type& l) + { + return symbol_type (token::TOKEN_SOCKET_TYPE, l); + } +#endif +#if 201103L <= YY_CPLUSPLUS + static + symbol_type + make_UNIX (location_type l) + { + return symbol_type (token::TOKEN_UNIX, std::move (l)); + } +#else + static + symbol_type + make_UNIX (const location_type& l) + { + return symbol_type (token::TOKEN_UNIX, l); } #endif #if 201103L <= YY_CPLUSPLUS @@ -2099,8 +2160,8 @@ switch (yykind) /// Constants. enum { - yylast_ = 197, ///< Last index in yytable_. - yynnts_ = 103, ///< Number of nonterminal symbols. + yylast_ = 219, ///< Last index in yytable_. + yynnts_ = 110, ///< Number of nonterminal symbols. yyfinal_ = 8 ///< Termination state number. }; @@ -2150,10 +2211,10 @@ switch (yykind) 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, - 45 + 45, 46, 47, 48 }; // Last valid token kind. - const int code_max = 300; + const int code_max = 303; if (t <= 0) return symbol_kind::S_YYEOF; @@ -2175,6 +2236,7 @@ switch (yykind) case symbol_kind::S_value: // value case symbol_kind::S_map_value: // map_value case symbol_kind::S_socket_type_value: // socket_type_value + case symbol_kind::S_auth_type_value: // auth_type_value value.copy< ElementPtr > (YY_MOVE (that.value)); break; @@ -2226,6 +2288,7 @@ switch (yykind) case symbol_kind::S_value: // value case symbol_kind::S_map_value: // map_value case symbol_kind::S_socket_type_value: // socket_type_value + case symbol_kind::S_auth_type_value: // auth_type_value value.move< ElementPtr > (YY_MOVE (s.value)); break; @@ -2308,7 +2371,7 @@ switch (yykind) #line 14 "agent_parser.yy" } } // isc::agent -#line 2312 "agent_parser.h" +#line 2375 "agent_parser.h" diff --git a/src/bin/agent/location.hh b/src/bin/agent/location.hh index c440be17db..8d99d97acb 100644 --- a/src/bin/agent/location.hh +++ b/src/bin/agent/location.hh @@ -1,4 +1,4 @@ -// Generated 202009120852 +// Generated 202009121616 // A Bison parser, made by GNU Bison 3.7.2. // Locations for Bison parsers in C++ diff --git a/src/bin/agent/position.hh b/src/bin/agent/position.hh index fb813a89c6..b9faa8db69 100644 --- a/src/bin/agent/position.hh +++ b/src/bin/agent/position.hh @@ -1,4 +1,4 @@ -// Generated 202009120852 +// Generated 202009121616 // A Bison parser, made by GNU Bison 3.7.2. // Starting with Bison 3.2, this file is useless: the structure it diff --git a/src/bin/agent/stack.hh b/src/bin/agent/stack.hh index ddc4320848..430d2020d9 100644 --- a/src/bin/agent/stack.hh +++ b/src/bin/agent/stack.hh @@ -1,4 +1,4 @@ -// Generated 202009120852 +// Generated 202009121616 // A Bison parser, made by GNU Bison 3.7.2. // Starting with Bison 3.2, this file is useless: the structure it -- GitLab From f907a0834544bf28af36c6e4fb1263f1a9c3f15b Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Sun, 13 Sep 2020 22:03:20 +0200 Subject: [PATCH 25/33] [#1304] Checkpoint before regen --- doc/examples/agent/comments.json | 25 +-- doc/examples/agent/simple.json | 44 +++-- doc/sphinx/arm/agent.rst | 26 +-- src/bin/agent/agent_lexer.ll | 6 +- src/bin/agent/agent_parser.cc | 2 +- src/bin/agent/agent_parser.yy | 5 +- src/bin/agent/ca_cfg_mgr.cc | 23 +-- src/bin/agent/ca_cfg_mgr.h | 43 ++--- src/bin/agent/ca_response_creator.cc | 11 +- src/bin/agent/parser_context.cc | 15 ++ src/bin/agent/parser_context.h | 13 ++ src/bin/agent/simple_parser.cc | 36 ++-- src/bin/agent/simple_parser.h | 7 +- src/bin/agent/tests/ca_cfg_mgr_unittests.cc | 158 ++++++++++-------- .../tests/ca_response_creator_unittests.cc | 15 +- src/lib/http/Makefile.am | 4 +- src/lib/http/auth_config.h | 84 ++++++++++ src/lib/http/basic_auth_config.cc | 140 +++++++++++++++- src/lib/http/basic_auth_config.h | 29 +++- src/lib/http/response_creator_auth.cc | 75 --------- src/lib/http/response_creator_auth.h | 38 ----- .../http/tests/basic_auth_config_unittests.cc | 136 +++++++++++---- .../http/tests/response_creator_unittests.cc | 89 +++++----- 23 files changed, 644 insertions(+), 380 deletions(-) create mode 100644 src/lib/http/auth_config.h delete mode 100644 src/lib/http/response_creator_auth.cc delete mode 100644 src/lib/http/response_creator_auth.h diff --git a/doc/examples/agent/comments.json b/doc/examples/agent/comments.json index afa706e27c..01eb15bb25 100644 --- a/doc/examples/agent/comments.json +++ b/doc/examples/agent/comments.json @@ -10,17 +10,22 @@ "http-host": "127.0.0.1", "http-port": 8000, - "basic-authentication-realm": "kea-control-agent", - // In basic HTTP authentication - "basic-authentications": - [ - { - "comment": "admin is authorized", - "user": "admin", - "password": "1234" - } - ], + // In authentication + "authentication": + { + "comment": "basic HTTP authentication", + + // In basic HTTP authentication clients + "clients": + [ + { + "comment": "admin is authorized", + "user": "admin", + "password": "1234" + } + ] + }, // In control socket "control-sockets": diff --git a/doc/examples/agent/simple.json b/doc/examples/agent/simple.json index db37248568..7aa741d33d 100644 --- a/doc/examples/agent/simple.json +++ b/doc/examples/agent/simple.json @@ -11,27 +11,35 @@ // Another mandatory parameter is the HTTP port. "http-port": 8000, - // An optional parameter is the basic HTTP authentication realm. - // Its default is "kea-control-agent". - "basic-authentication-realm": "kea-control-agent", + // Optional authentication. + "authentication": + { + // Required authentication type. The only supported value is + // basic for the basic HTTP authentication. + "type": "basic", - // This list specifies the user ids and passwords to use for - // basic HTTP authentication. If empty or not present any client - // is authorized. - "basic-authentications": - [ - // This specifies an authorized client. - { - "comment": "admin is authorized", + // An optional parameter is the basic HTTP authentication realm. + // Its default is "kea-control-agent". + "realm": "kea-control-agent", - // The user id must not be empty or contain the ':' character. - // It is a mandatory parameter. - "user": "admin", + // This list specifies the user ids and passwords to use for + // basic HTTP authentication. If empty or not present any client + // is authorized. + "clients": + [ + // This specifies an authorized client. + { + "comment": "admin is authorized", - // If password is not specified an empty password is used. - "password": "1234" - } - ], + // The user id must not be empty or contain the ':' + // character. It is a mandatory parameter. + "user": "admin", + + // If password is not specified an empty password is used. + "password": "1234" + } + ] + }, // This map specifies where control channel of each server is configured // to listen on. See 'control-socket' object in the respective diff --git a/doc/sphinx/arm/agent.rst b/doc/sphinx/arm/agent.rst index a65d2edaa3..dda3268a95 100644 --- a/doc/sphinx/arm/agent.rst +++ b/doc/sphinx/arm/agent.rst @@ -50,7 +50,15 @@ The following example demonstrates the basic CA configuration. "Control-agent": { "http-host": "10.20.30.40", "http-port": 8000, - "basic-authentication-realm": "kea-control-agent", + "authentication": { + "type": "basic", + "realm": "kea-control-agent", + "clients": [ + { + "user": "admin", + "password": "1234" + } ] + }, "control-sockets": { "dhcp4": { @@ -69,12 +77,6 @@ The following example demonstrates the basic CA configuration. }, }, - "basic-authentications": [ - { - "user": "admin", - "password": "1234" - } ], - "hooks-libraries": [ { "library": "/opt/local/control-agent-commands.so", @@ -142,11 +144,15 @@ against not authorized uses of the control agent by local users. For the protection against remote attackers HTTPS and reverse proxy of :ref:`agent-secure-connection` provide a stronger security. -The ``basic-authentication-realm`` is used for error message when -the basic HTTP authentication is mandatory but the client is not +The authentication is described in the ``authentication`` block +with the mandatory ``type`` parameter which selects the authentication. +Currently only the basic HTTP authentication (type basic) is supported. + +The ``realm`` authentication parameter is used for error message when +the basic HTTP authentication is required but the client is not authorized. -When the ``basic-authentications`` list is configured and not empty +When the ``clients`` authentication list is configured and not empty the basic HTTP authentication is required. Each element of the list specifies a user id and a password. The user id is mandatory, must be not empty and must not contain the colon (:) character. The diff --git a/src/bin/agent/agent_lexer.ll b/src/bin/agent/agent_lexer.ll index 962abf0c1c..37d3df9fda 100644 --- a/src/bin/agent/agent_lexer.ll +++ b/src/bin/agent/agent_lexer.ll @@ -203,9 +203,10 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence} \"user-context\" { switch(driver.ctx_) { case ParserContext::AGENT: + case ParserContext::AUTHENTICATION; + case ParserContext::CLIENTS: case ParserContext::SERVER: case ParserContext::LOGGERS: - case ParserContext::CLIENTS: return AgentParser::make_USER_CONTEXT(driver.loc_); default: return AgentParser::make_STRING("user-context", driver.loc_); @@ -215,9 +216,10 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence} \"comment\" { switch(driver.ctx_) { case ParserContext::AGENT: + case ParserContext::AUTHENTICATION; + case ParserContext::CLIENTS: case ParserContext::SERVER: case ParserContext::LOGGERS: - case ParserContext::CLIENTS: return AgentParser::make_COMMENT(driver.loc_); default: return AgentParser::make_STRING("comment", driver.loc_); diff --git a/src/bin/agent/agent_parser.cc b/src/bin/agent/agent_parser.cc index afc2020689..ad0cdd029b 100644 --- a/src/bin/agent/agent_parser.cc +++ b/src/bin/agent/agent_parser.cc @@ -1269,7 +1269,7 @@ namespace isc { namespace agent { #line 529 "agent_parser.yy" { // Add unique here - ctx.enter(ctx.NO_KEYWORD); + ctx.enter(ctx.NO_KEYWORDS); } #line 1275 "agent_parser.cc" break; diff --git a/src/bin/agent/agent_parser.yy b/src/bin/agent/agent_parser.yy index 36c686288b..c6294e2691 100644 --- a/src/bin/agent/agent_parser.yy +++ b/src/bin/agent/agent_parser.yy @@ -513,6 +513,9 @@ auth_params: auth_param auth_param: auth_type | realm | clients + | comment + | user_context + | unknown_map_entry ; auth_type: TYPE { @@ -528,7 +531,7 @@ auth_type_value: BASIC { $$ = ElementPtr(new StringElement("basic", ctx.loc2pos( realm: REALM { // Add unique here - ctx.enter(ctx.NO_KEYWORD); + ctx.enter(ctx.NO_KEYWORDS); } COLON STRING { ElementPtr realm(new StringElement($4, ctx.loc2pos(@4))); ctx.stack_.back()->set("realm", realm); diff --git a/src/bin/agent/ca_cfg_mgr.cc b/src/bin/agent/ca_cfg_mgr.cc index 6cf058357b..507c3409f4 100644 --- a/src/bin/agent/ca_cfg_mgr.cc +++ b/src/bin/agent/ca_cfg_mgr.cc @@ -10,6 +10,7 @@ #include #include #include +#include #include using namespace isc::config; @@ -21,15 +22,13 @@ namespace isc { namespace agent { CtrlAgentCfgContext::CtrlAgentCfgContext() - : http_host_(""), http_port_(0), basic_auth_realm_("") { + : http_host_(""), http_port_(0) { } CtrlAgentCfgContext::CtrlAgentCfgContext(const CtrlAgentCfgContext& orig) : ConfigBase(), ctrl_sockets_(orig.ctrl_sockets_), http_host_(orig.http_host_), http_port_(orig.http_port_), - basic_auth_realm_(orig.basic_auth_realm_), - hooks_config_(orig.hooks_config_), - basic_auth_config_(orig.basic_auth_config_) { + hooks_config_(orig.hooks_config_), auth_config_(orig.auth_config_) { } CtrlAgentCfgMgr::CtrlAgentCfgMgr() @@ -53,8 +52,8 @@ CtrlAgentCfgMgr::getConfigSummary(const uint32_t /*selection*/) { s << ctx->getControlSocketInfoSummary(); // Add something if authentication is required. - const isc::http::BasicHttpAuthConfig& auth = ctx->getBasicAuthConfig(); - if (!auth.getClientList().empty()) { + const isc::http::HttpAuthConfigPtr& auth = ctx->getAuthConfig(); + if (auth && !auth->empty()) { s << ", requires basic HTTP authentication"; } @@ -160,9 +159,10 @@ CtrlAgentCfgContext::toElement() const { ca->set("http-host", Element::create(http_host_)); // Set http-port ca->set("http-port", Element::create(static_cast(http_port_))); - // Set basic-authentication-realm - ca->set("basic-authentication-realm", Element::create(basic_auth_realm_)); - // Set hooks-libraries + // Set authentication + if (auth_config_) { + ca->set("authentication", auth_config_->toElement()); + } ca->set("hooks-libraries", hooks_config_.toElement()); // Set control-sockets ElementPtr control_sockets = Element::createMap(); @@ -171,11 +171,6 @@ CtrlAgentCfgContext::toElement() const { control_sockets->set(si->first, socket); } ca->set("control-sockets", control_sockets); - // Set basic HTTP authentication - const isc::http::BasicHttpAuthConfig& auth = basic_auth_config_; - if (!basic_auth_config_.getClientList().empty()) { - ca->set("basic-authentications", basic_auth_config_.toElement()); - } // Set Control-agent ElementPtr result = Element::createMap(); result->set("Control-agent", ca); diff --git a/src/bin/agent/ca_cfg_mgr.h b/src/bin/agent/ca_cfg_mgr.h index ae39e17860..7c09ce397a 100644 --- a/src/bin/agent/ca_cfg_mgr.h +++ b/src/bin/agent/ca_cfg_mgr.h @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include #include @@ -99,18 +99,22 @@ public: return (http_port_); } - /// @brief Sets basic-authentication-realm parameter + /// @brief Sets HTTP authentication configuration. /// - /// @param real Basic HTTP authentication realm - void setBasicAuthRealm(const std::string& realm) { - basic_auth_realm_ = realm; + /// @note Only the basic HTTP authentication is supported. + /// + /// @param auth_config HTTP authentication configuration. + void setAuthConfig(const isc::http::HttpAuthConfigPtr& auth_config) { + auth_config_ = auth_config; } - /// @brief Returns basic-authentication-realm parameter + /// @brief Returns HTTP authentication configuration + /// + /// @note Only the basic HTTP authentication is supported. /// - /// @return Basic HTTP authentication realm. - std::string getBasicAuthRealm() const { - return (basic_auth_realm_); + /// @return HTTP authentication configuration. + const isc::http::HttpAuthConfigPtr& getAuthConfig() const { + return (auth_config_); } /// @brief Returns non-const reference to configured hooks libraries. @@ -127,22 +131,6 @@ public: return (hooks_config_); } - /// @brief Returns non-const reference to configured basic HTTP - /// authentification clients. - /// - /// @return non-const reference to configured basic auth clients. - isc::http::BasicHttpAuthConfig& getBasicAuthConfig() { - return (basic_auth_config_); - } - - /// @brief Returns const reference to configured basic HTTP - /// authentification clients. - /// - /// @return const reference to configured basic auth clients. - const isc::http::BasicHttpAuthConfig& getBasicAuthConfig() const { - return (basic_auth_config_); - } - /// @brief Unparse a configuration object /// /// Returns an element which must parse into the same object, i.e. @@ -178,14 +166,11 @@ private: /// TCP port the CA should listen on. uint16_t http_port_; - /// Basic HTTP authentication realm. - std::string basic_auth_realm_; - /// @brief Configured hooks libraries. isc::hooks::HooksConfig hooks_config_; /// @brief Configured basic HTTP authentification clients. - isc::http::BasicHttpAuthConfig basic_auth_config_; + isc::http::HttpAuthConfigPtr auth_config_; }; /// @brief Ctrl Agent Configuration Manager. diff --git a/src/bin/agent/ca_response_creator.cc b/src/bin/agent/ca_response_creator.cc index 75fb93b6cd..702d031688 100644 --- a/src/bin/agent/ca_response_creator.cc +++ b/src/bin/agent/ca_response_creator.cc @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -81,11 +80,11 @@ createDynamicHttpResponse(const ConstHttpRequestPtr& request) { if (cfgmgr) { ctx = cfgmgr->getCtrlAgentCfgContext(); if (ctx) { - const BasicHttpAuthConfig& auth = ctx->getBasicAuthConfig(); - const BasicHttpAuthMap& auth_map = auth.getCredentialMap(); - // Check authentication. - http_response = checkAuth(*this, request, auth_map, - ctx->getBasicAuthRealm()); + const HttpAuthConfigPtr& auth = ctx->getAuthConfig(); + if (auth) { + // Check authentication. + http_response = auth->checkAuth(*this, request); + } } } } diff --git a/src/bin/agent/parser_context.cc b/src/bin/agent/parser_context.cc index c0a1a4aa5e..ff517b56d4 100644 --- a/src/bin/agent/parser_context.cc +++ b/src/bin/agent/parser_context.cc @@ -96,6 +96,21 @@ ParserContext::loc2pos(isc::agent::location& loc) return (isc::data::Element::Position(file, line, pos)); } +void +ParserContext::require(const std::string& name, + isc::data::Element::Position open_loc, + isc::data::Element::Position close_loc) +{ + ConstElementPtr value = stack_.back()->get(name); + if (!value) { + isc_throw(ParseError, + "missing parameter '" << name << "' (" + << stack_.back()->getPosition() << ") [" + << contextName() << " map between " + << open_loc << " and " << close_loc << "]"); + } +} + void ParserContext::enter(const LexerContext& ctx) { diff --git a/src/bin/agent/parser_context.h b/src/bin/agent/parser_context.h index ffcd8e3530..a8fdea861e 100644 --- a/src/bin/agent/parser_context.h +++ b/src/bin/agent/parser_context.h @@ -147,6 +147,19 @@ public: /// @return Position in format accepted by Element isc::data::Element::Position loc2pos(isc::agent::location& loc); + /// @brief Check if a required parameter is present + /// + /// Check if a required parameter is present in the map at the top + /// of the stack and raise an error when it is not. + /// + /// @param name name of the parameter to check + /// @param open_loc location of the opening curly bracket + /// @param close_loc location of the closing curly bracket + /// @throw ParseError + void require(const std::string& name, + isc::data::Element::Position open_loc, + isc::data::Element::Position close_loc); + /// @brief Defines syntactic contexts for lexical tie-ins typedef enum { ///< This one is used in pure JSON mode. diff --git a/src/bin/agent/simple_parser.cc b/src/bin/agent/simple_parser.cc index f347ea40f9..1890608d33 100644 --- a/src/bin/agent/simple_parser.cc +++ b/src/bin/agent/simple_parser.cc @@ -11,6 +11,7 @@ #include #include #include +#include #include using namespace isc::data; @@ -36,15 +37,20 @@ namespace agent { /// /// These are global Control Agent parameters. const SimpleDefaults AgentSimpleParser::AGENT_DEFAULTS = { - { "http-host", Element::string, "127.0.0.1" }, - { "http-port", Element::integer, "8000" }, - { "basic-authentication-realm", Element::string, "kea-control-agent" } + { "http-host", Element::string, "127.0.0.1" }, + { "http-port", Element::integer, "8000" } +}; + +/// @brief This table defines default values for authentication. +const SimpleDefaults AgentSimpleParser::AUTH_DEFAULTS = { + { "type", Element::string, "basic" }, + { "realm", Element::string, "kea-control-agent" } }; /// @brief This table defines default values for control sockets. /// const SimpleDefaults AgentSimpleParser::SOCKET_DEFAULTS = { - { "socket-type", Element::string, "unix"} + { "socket-type", Element::string, "unix" } }; /// @} @@ -59,6 +65,15 @@ size_t AgentSimpleParser::setAllDefaults(const isc::data::ElementPtr& global) { // Set global defaults first. cnt = setDefaults(global, AGENT_DEFAULTS); + // After set the defaults for authentication if it exists. + ConstElementPtr authentication = global->get("authentication"); + if (authentication) { + ElementPtr auth = boost::const_pointer_cast(authentication); + if (auth) { + cnt += SimpleParser::setDefaults(auth, AUTH_DEFAULTS); + } + } + // Now set the defaults for control-sockets, if any. ConstElementPtr sockets = global->get("control-sockets"); if (sockets) { @@ -89,8 +104,6 @@ AgentSimpleParser::parse(const CtrlAgentCfgContextPtr& ctx, // Let's get the HTTP parameters first. ctx->setHttpHost(SimpleParser::getString(config, "http-host")); ctx->setHttpPort(SimpleParser::getIntType(config, "http-port")); - ctx->setBasicAuthRealm(SimpleParser::getString(config, - "basic-authentication-realm")); // Control sockets are second. ConstElementPtr ctrl_sockets = config->get("control-sockets"); @@ -102,9 +115,13 @@ AgentSimpleParser::parse(const CtrlAgentCfgContextPtr& ctx, } // Basic HTTP authentications are third. - ConstElementPtr auth_config = config->get("basic-authentications"); - ctx->getBasicAuthConfig().clear(); - ctx->getBasicAuthConfig().parse(auth_config); + ConstElementPtr auth_config = config->get("authentications"); + if (auth_config) { + using namespace isc::http; + BasicHttpAuthConfigPtr auth(new BasicHttpAuthConfig()); + auth->parse(auth_config); + ctx->setAuthConfig(auth); + } // User context can be done at anytime. ConstElementPtr user_context = config->get("user-context"); @@ -113,7 +130,6 @@ AgentSimpleParser::parse(const CtrlAgentCfgContextPtr& ctx, } // Finally, let's get the hook libs! - using namespace isc::hooks; HooksConfig& libraries = ctx->getHooksConfig(); ConstElementPtr hooks = config->get("hooks-libraries"); diff --git a/src/bin/agent/simple_parser.h b/src/bin/agent/simple_parser.h index f01aacca30..6d29fbf205 100644 --- a/src/bin/agent/simple_parser.h +++ b/src/bin/agent/simple_parser.h @@ -1,4 +1,4 @@ -// Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC") +// Copyright (C) 2017-2020 Internet Systems Consortium, Inc. ("ISC") // // This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this @@ -43,9 +43,10 @@ public: // see simple_parser.cc for comments for those parameters static const isc::data::SimpleDefaults AGENT_DEFAULTS; + static const isc::data::SimpleDefaults AUTH_DEFAULTS; static const isc::data::SimpleDefaults SOCKET_DEFAULTS; }; -}; -}; +} +} #endif diff --git a/src/bin/agent/tests/ca_cfg_mgr_unittests.cc b/src/bin/agent/tests/ca_cfg_mgr_unittests.cc index a77b0012a3..480e8c2234 100644 --- a/src/bin/agent/tests/ca_cfg_mgr_unittests.cc +++ b/src/bin/agent/tests/ca_cfg_mgr_unittests.cc @@ -10,7 +10,9 @@ #include #include #include +#include #include +#include #include #include @@ -63,9 +65,6 @@ TEST(CtrlAgentCfgMgr, contextHttpParams) { ctx.setHttpHost("alnitak"); EXPECT_EQ("alnitak", ctx.getHttpHost()); - - ctx.setBasicAuthRealm("foobar"); - EXPECT_EQ("foobar", ctx.getBasicAuthRealm()); } // Tests if context can store and retrieve control socket information. @@ -126,15 +125,16 @@ TEST(CtrlAgentCfgMgr, contextSocketInfoCopy) { EXPECT_NO_THROW(ctx.setHttpPort(12345)); EXPECT_NO_THROW(ctx.setHttpHost("bellatrix")); - EXPECT_NO_THROW(ctx.setBasicAuthRealm("foobar")); HooksConfig& libs = ctx.getHooksConfig(); string exp_name("testlib1.so"); ConstElementPtr exp_param(new StringElement("myparam")); libs.add(exp_name, exp_param); - BasicHttpAuthConfig& auth = ctx.getBasicAuthConfig(); - auth.add("foo", "bar"); + BasicHttpAuthConfigPtr auth(new BasicHttpAuthConfig()); + auth->setRealm("foobar"); + auth->add("foo", "bar"); + EXPECT_NO_THROW(ctx.setAuthConfig(auth)); // Make a copy. ConfigPtr copy_base(ctx.clone()); @@ -144,7 +144,6 @@ TEST(CtrlAgentCfgMgr, contextSocketInfoCopy) { // Now check the values returned EXPECT_EQ(12345, copy->getHttpPort()); EXPECT_EQ("bellatrix", copy->getHttpHost()); - EXPECT_EQ("foobar", copy->getBasicAuthRealm()); // Check socket info ASSERT_TRUE(copy->getControlSocketInfo("d2")); @@ -161,9 +160,10 @@ TEST(CtrlAgentCfgMgr, contextSocketInfoCopy) { ASSERT_TRUE(libs2[0].second); EXPECT_EQ(exp_param->str(), libs2[0].second->str()); - // Check basic HTTP authentication - const BasicHttpAuthConfig& auth2 = copy->getBasicAuthConfig(); - EXPECT_EQ(auth.toElement()->str(), auth2.toElement()->str()); + // Check authentication + const HttpAuthConfigPtr& auth2 = copy->getAuthConfig(); + ASSERT_TRUE(auth2); + EXPECT_EQ(auth->toElement()->str(), auth2->toElement()->str()); } @@ -186,21 +186,24 @@ TEST(CtrlAgentCfgMgr, contextHookParams) { EXPECT_EQ(libs.get(), stored_libs.get()); } -// Test if the context can store and retrieve basic HTTP authentication clients. -TEST(CtrlAgentCfgMgr, contextBasicAuth) { +// Test if the context can store and retrieve basic HTTP authentication +// configuration. +TEST(CtrlAgentCfgMgr, contextAuthConfig) { CtrlAgentCfgContext ctx; // By default there should be no authentication. - BasicHttpAuthConfig& auth = ctx.getBasicAuthConfig(); - EXPECT_TRUE(auth.getClientList().empty()); - - auth.add("foo", "bar"); - auth.add("test", "123\xa3"); - - const BasicHttpAuthConfig& stored_auth = ctx.getBasicAuthConfig(); - EXPECT_EQ(2, stored_auth.getClientList().size()); - - EXPECT_EQ(auth.toElement()->str(), stored_auth.toElement()->str()); + EXPECT_FALSE(ctx.getAuthConfig()); + BasicHttpAuthConfigPtr auth(new BasicHttpAuthConfig()); + EXPECT_NO_THROW(ctx.setAuthConfig(auth)); + + auth->setRealm("foobar"); + auth->add("foo", "bar"); + auth->add("test", "123\xa3"); + + const HttpAuthConfigPtr& stored_auth = ctx.getAuthConfig(); + ASSERT_TRUE(stored_auth); + EXPECT_FALSE(stored_auth->empty()); + EXPECT_EQ(auth->toElement()->str(), stored_auth->toElement()->str()); } /// Control Agent configurations used in tests. @@ -211,15 +214,13 @@ const char* AGENT_CONFIGS[] = { // Configuration 1: http parameters only (no control sockets, not hooks) "{ \"http-host\": \"betelgeuse\",\n" - " \"http-port\": 8001,\n" - " \"basic-authentication-realm\": \"foobar\"\n" + " \"http-port\": 8001\n" "}", // Configuration 2: http and 1 socket "{\n" " \"http-host\": \"betelgeuse\",\n" " \"http-port\": 8001,\n" - " \"basic-authentication-realm\": \"foobar\",\n" " \"control-sockets\": {\n" " \"dhcp4\": {\n" " \"socket-name\": \"/tmp/socket-v4\"\n" @@ -231,7 +232,6 @@ const char* AGENT_CONFIGS[] = { "{\n" " \"http-host\": \"betelgeuse\",\n" " \"http-port\": 8001,\n" - " \"basic-authentication-realm\": \"foobar\",\n" " \"control-sockets\": {\n" " \"dhcp4\": {\n" " \"socket-name\": \"/tmp/socket-v4\"\n" @@ -251,7 +251,6 @@ const char* AGENT_CONFIGS[] = { "{\n" " \"http-host\": \"betelgeuse\",\n" " \"http-port\": 8001,\n" - " \"basic-authentication-realm\": \"foobar\",\n" " \"control-sockets\": {\n" " \"dhcp4\": {\n" " \"socket-name\": \"/tmp/socket-v4\"\n" @@ -271,7 +270,6 @@ const char* AGENT_CONFIGS[] = { "{\n" " \"http-host\": \"betelgeuse\",\n" " \"http-port\": 8001,\n" - " \"basic-authentication-realm\": \"foobar\",\n" " \"control-sockets\": {\n" " \"d2\": {\n" " \"socket-name\": \"/tmp/socket-d2\"\n" @@ -283,7 +281,6 @@ const char* AGENT_CONFIGS[] = { "{\n" " \"http-host\": \"betelgeuse\",\n" " \"http-port\": 8001,\n" - " \"basic-authentication-realm\": \"foobar\",\n" " \"control-sockets\": {\n" " \"dhcp6\": {\n" " \"socket-name\": \"/tmp/socket-v6\"\n" @@ -291,25 +288,28 @@ const char* AGENT_CONFIGS[] = { " }\n" "}", - // Configuration 7: http, 1 socket and basic authentication + // Configuration 7: http, 1 socket and authentication "{\n" " \"http-host\": \"betelgeuse\",\n" " \"http-port\": 8001,\n" - " \"basic-authentication-realm\": \"foobar\",\n" + " \"authentication\": {\n" + " \"type\": \"basic\",\n" + " \"realm\": \"foobar\",\n" + " \"clients\": [" + " {" + " \"user\": \"foo\",\n" + " \"password\": \"bar\"\n" + " },{\n" + " \"user\": \"test\",\n" + " \"password\": \"123\\u00a3\"\n" + " }\n" + " ]\n" + " },\n" " \"control-sockets\": {\n" " \"dhcp4\": {\n" " \"socket-name\": \"/tmp/socket-v4\"\n" " }\n" - " },\n" - " \"basic-authentications\": [" - " {" - " \"user\": \"foo\",\n" - " \"password\": \"bar\"\n" - " },{\n" - " \"user\": \"test\",\n" - " \"password\": \"123\\u00a3\"\n" - " }\n" - " ]\n" + " }\n" "}", // Configuration 8: http and 2 sockets with user contexts and comments @@ -317,7 +317,21 @@ const char* AGENT_CONFIGS[] = { " \"user-context\": { \"comment\": \"Indirect comment\" },\n" " \"http-host\": \"betelgeuse\",\n" " \"http-port\": 8001,\n" - " \"basic-authentication-realm\": \"foobar\",\n" + " \"authentication\": {\n" + " \"comment\": \"basic HTTP authentication\",\n" + " \"type\": \"basic\",\n" + " \"realm\": \"foobar\",\n" + " \"clients\": [" + " {" + " \"comment\": \"foo is authorized\",\n" + " \"user\": \"foo\",\n" + " \"password\": \"bar\"\n" + " },{\n" + " \"user\": \"test\",\n" + " \"user-context\": { \"no password\": true }\n" + " }\n" + " ]\n" + " },\n" " \"control-sockets\": {\n" " \"dhcp4\": {\n" " \"comment\": \"dhcp4 socket\",\n" @@ -327,17 +341,7 @@ const char* AGENT_CONFIGS[] = { " \"socket-name\": \"/tmp/socket-v6\",\n" " \"user-context\": { \"version\": 1 }\n" " }\n" - " },\n" - " \"basic-authentications\": [" - " {" - " \"comment\": \"foo is authorized\",\n" - " \"user\": \"foo\",\n" - " \"password\": \"bar\"\n" - " },{\n" - " \"user\": \"test\",\n" - " \"user-context\": { \"no password\": true }\n" - " }\n" - " ]\n" + " }\n" "}" }; @@ -389,7 +393,6 @@ TEST_F(AgentParserTest, configParseHttpOnly) { ASSERT_TRUE(ctx); EXPECT_EQ("betelgeuse", ctx->getHttpHost()); EXPECT_EQ(8001, ctx->getHttpPort()); - EXPECT_EQ("foobar", ctx->getBasicAuthRealm()); } // Tests if a single socket can be configured. BTW this test also checks @@ -482,13 +485,20 @@ TEST_F(AgentParserTest, configParseHooks) { // This test checks that the config file with basic HTTP authentication can be // loaded. -TEST_F(AgentParserTest, configParseBasicAuth) { +TEST_F(AgentParserTest, configParseAuth) { configParse(AGENT_CONFIGS[7], 0); CtrlAgentCfgContextPtr ctx = cfg_mgr_.getCtrlAgentCfgContext(); - const BasicHttpAuthConfig& auth = ctx->getBasicAuthConfig(); + const HttpAuthConfigPtr& auth = ctx->getAuthConfig(); + ASSERT_TRUE(auth); + const BasicHttpAuthConfigPtr& basic_auth = + boost::dynamic_pointer_cast(auth); + ASSERT_TRUE(basic_auth); + + // Check realm + EXPECT_EQ("foobar", basic_auth->getRealm()); // Check credentails - auto credentials = auth.getCredentialMap(); + auto credentials = basic_auth->getCredentialMap(); EXPECT_EQ(2, credentials.size()); std::string user; EXPECT_NO_THROW(user = credentials.at("Zm9vOmJhcg==")); @@ -498,9 +508,10 @@ TEST_F(AgentParserTest, configParseBasicAuth) { // Check clients. BasicHttpAuthConfig expected; + expected.setRealm("foobar"); expected.add("foo", "bar"); expected.add("test", "123\xa3"); - EXPECT_EQ(expected.toElement()->str(), auth.toElement()->str()); + EXPECT_EQ(expected.toElement()->str(), basic_auth->toElement()->str()); } // This test checks comments. @@ -538,22 +549,33 @@ TEST_F(AgentParserTest, comments) { ASSERT_TRUE(ctx6->get("version")); EXPECT_EQ("1", ctx6->get("version")->str()); - // Check basic HTTP authentication comment. - const BasicHttpAuthConfig& auth = agent_ctx->getBasicAuthConfig(); - auto clients = auth.getClientList(); - ASSERT_EQ(2, clients.size()); - ConstElementPtr ctx7 = clients.front().getContext(); + // Check authentication comment. + const HttpAuthConfigPtr& auth = agent_ctx->getAuthConfig(); + ASSERT_TRUE(auth); + ConstElementPtr ctx7 = auth->getContext(); ASSERT_TRUE(ctx7); ASSERT_EQ(1, ctx7->size()); ASSERT_TRUE(ctx7->get("comment")); - EXPECT_EQ("\"foo is authorized\"", ctx7->get("comment")->str()); + EXPECT_EQ("\"basic HTTP authentication\"", ctx7->get("comment")->str()); - // Check basic HTTP authentication user context. - ConstElementPtr ctx8 = clients.back().getContext(); + // Check basic HTTP authentication client comment. + const BasicHttpAuthConfigPtr& basic_auth = + boost::dynamic_pointer_cast(auth); + ASSERT_TRUE(basic_auth); + auto clients = basic_auth->getClientList(); + ASSERT_EQ(2, clients.size()); + ConstElementPtr ctx8 = clients.front().getContext(); ASSERT_TRUE(ctx8); ASSERT_EQ(1, ctx8->size()); - ASSERT_TRUE(ctx8->get("no password")); - EXPECT_EQ("true", ctx8->get("no password")->str()); + ASSERT_TRUE(ctx8->get("comment")); + EXPECT_EQ("\"foo is authorized\"", ctx8->get("comment")->str()); + + // Check basic HTTP authentication client user context. + ConstElementPtr ctx9 = clients.back().getContext(); + ASSERT_TRUE(ctx9); + ASSERT_EQ(1, ctx9->size()); + ASSERT_TRUE(ctx9->get("no password")); + EXPECT_EQ("true", ctx9->get("no password")->str()); } } // end of anonymous namespace diff --git a/src/bin/agent/tests/ca_response_creator_unittests.cc b/src/bin/agent/tests/ca_response_creator_unittests.cc index 35028cdb4a..58bce6800e 100644 --- a/src/bin/agent/tests/ca_response_creator_unittests.cc +++ b/src/bin/agent/tests/ca_response_creator_unittests.cc @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -250,9 +251,10 @@ TEST_F(CtrlAgentResponseCreatorTest, noAuth) { // Require authentication. CtrlAgentCfgContextPtr ctx = getCtrlAgentCfgContext(); ASSERT_TRUE(ctx); - ctx->setBasicAuthRealm("ISC.ORG"); - BasicHttpAuthConfig& auth = ctx->getBasicAuthConfig(); - auth.add("foo", "bar"); + BasicHttpAuthConfigPtr auth(new BasicHttpAuthConfig()); + ASSERT_NO_THROW(ctx->setAuthConfig(auth)); + auth->setRealm("ISC.ORG"); + auth->add("foo", "bar"); HttpResponsePtr response; ASSERT_NO_THROW(response = response_creator_.createHttpResponse(request_)); @@ -290,8 +292,11 @@ TEST_F(CtrlAgentResponseCreatorTest, basicAuth) { // Require authentication. CtrlAgentCfgContextPtr ctx = getCtrlAgentCfgContext(); ASSERT_TRUE(ctx); - BasicHttpAuthConfig& auth = ctx->getBasicAuthConfig(); - auth.add("foo", "bar"); + BasicHttpAuthConfigPtr auth(new BasicHttpAuthConfig()); + ASSERT_NO_THROW(ctx->setAuthConfig(auth)); + // In fact the realm is used only on errors... set it anyway. + auth->setRealm("ISC.ORG"); + auth->add("foo", "bar"); HttpResponsePtr response; ASSERT_NO_THROW(response = response_creator_.createHttpResponse(request_)); diff --git a/src/lib/http/Makefile.am b/src/lib/http/Makefile.am index 34e5f500ec..08d3484af9 100644 --- a/src/lib/http/Makefile.am +++ b/src/lib/http/Makefile.am @@ -35,11 +35,11 @@ libkea_http_la_SOURCES += response.cc response.h libkea_http_la_SOURCES += response_parser.cc response_parser.h libkea_http_la_SOURCES += response_context.h libkea_http_la_SOURCES += response_creator.cc response_creator.h -libkea_http_la_SOURCES += response_creator_auth.cc response_creator_auth.h libkea_http_la_SOURCES += response_creator_factory.h libkea_http_la_SOURCES += response_json.cc response_json.h libkea_http_la_SOURCES += url.cc url.h libkea_http_la_SOURCES += basic_auth.cc basic_auth.h +libkea_http_la_SOURCES += auth_config.h libkea_http_la_SOURCES += basic_auth_config.cc basic_auth_config.h libkea_http_la_CXXFLAGS = $(AM_CXXFLAGS) @@ -91,6 +91,7 @@ endif # Specify the headers for copying into the installation directory tree. libkea_http_includedir = $(pkgincludedir)/http libkea_http_include_HEADERS = \ + auth_config.h \ basic_auth.h \ basic_auth_config.h \ client.h \ @@ -115,7 +116,6 @@ libkea_http_include_HEADERS = \ response.h \ response_context.h \ response_creator.h \ - response_creator_auth.h \ response_creator_factory.h \ response_json.h \ response_parser.h \ diff --git a/src/lib/http/auth_config.h b/src/lib/http/auth_config.h new file mode 100644 index 0000000000..a2450b50d8 --- /dev/null +++ b/src/lib/http/auth_config.h @@ -0,0 +1,84 @@ +// Copyright (C) 2020 Internet Systems Consortium, Inc. ("ISC") +// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef HTTP_AUTH_CONFIG_H +#define HTTP_AUTH_CONFIG_H + +#include +#include +#include +#include +#include +#include +#include + +namespace isc { +namespace http { + +/// @brief Base type of HTTP authentication configuration. +class HttpAuthConfig : public isc::data::UserContext, + public isc::data::CfgToElement { +public: + + /// @brief Destructor. + virtual ~HttpAuthConfig() { } + + /// @brief Set the realm. + /// + /// @param realm New realm. + void setRealm(const std::string& realm) { + realm_ = realm; + } + + /// @brief Returns the realm. + /// + /// @return The basic HTTP authentication realm. + const std::string& getRealm() const { + return (realm_); + } + + /// @brief Empty predicate. + /// @return true if the configuration is empty so authentication + /// is not required. + virtual bool empty() const = 0; + + /// @brief Clear configuration. + virtual void clear() = 0; + + /// @brief Parses HTTP authentication configuration. + /// + /// @param config Element holding the basic HTTP authentication + /// configuration to be parsed. + /// @throw DhcpConfigError when the configuration is invalid. + virtual void parse(const isc::data::ConstElementPtr& config) = 0; + + /// @brief Unparses HTTP authentication configuration. + /// + /// @return A pointer to unparsed HTTP authentication configuration. + virtual isc::data::ElementPtr toElement() const = 0; + + /// @brief Validate HTTP request. + /// + /// @param creator The HTTP response creator. + /// @param request The HTTP request to validate. + /// @return Error HTTP response if validation failed, null otherwise. + virtual isc::http::HttpResponseJsonPtr + checkAuth(const isc::http::HttpResponseCreator& creator, + const isc::http::ConstHttpRequestPtr& request) const = 0; + +private: + + /// @brief The realm. + std::string realm_; +}; + +/// @brief Type of shared pointers to HTTP authentication configuration. +typedef boost::shared_ptr HttpAuthConfigPtr; + +} // end of namespace isc::http +} // end of namespace isc + +#endif // endif HTTP_AUTH_CONFIG_H diff --git a/src/lib/http/basic_auth_config.cc b/src/lib/http/basic_auth_config.cc index d6213f5465..b43cb15a39 100644 --- a/src/lib/http/basic_auth_config.cc +++ b/src/lib/http/basic_auth_config.cc @@ -7,10 +7,13 @@ #include #include +#include +#include using namespace isc; using namespace isc::data; using namespace isc::dhcp; +using namespace isc::util; using namespace std; namespace isc { @@ -56,13 +59,30 @@ BasicHttpAuthConfig::clear() { map_.clear(); } +bool +BasicHttpAuthConfig::empty() const { + return (map_.empty()); +} + ElementPtr BasicHttpAuthConfig::toElement() const { - ElementPtr result = Element::createList(); + ElementPtr result = Element::createMap(); + + // Set user-context + contextToElement(result); + + // Set type + result->set("type", Element::create(string("basic"))); + + // Set realm + result->set("realm", Element::create(getRealm())); + // Set clients + ElementPtr clients = Element::createList(); for (auto client : list_) { - result->add(client.toElement()); + clients->add(client.toElement()); } + result->set("clients", clients); return (result); } @@ -72,21 +92,68 @@ BasicHttpAuthConfig::parse(const ConstElementPtr& config) { if (!config) { return; } - if (config->getType() != Element::list) { - isc_throw(DhcpConfigError, "basic-authentications must be a list (" + if (config->getType() != Element::map) { + isc_throw(DhcpConfigError, "authentication must be a map (" << config->getPosition() << ")"); } - for (auto client : config->listValue()) { + + // Get and verify the type. + ConstElementPtr type = config->get("type"); + if (!type) { + isc_throw(DhcpConfigError, "type is required in authentication (" + << config->getPosition() << ")"); + } + if (type->getType() != Element::string) { + isc_throw(DhcpConfigError, "type is must be a string (" + << type->getPosition() << ")"); + } + if (type->stringValue() != "basic") { + isc_throw(DhcpConfigError, "only basic HTTP authentication is " + << "supported: type is '" << type->stringValue() + << "' not 'basic' (" << type->getPosition() << ")"); + } + + // Get the realm. + ConstElementPtr realm = config->get("realm"); + if (realm) { + if (realm->getType() != Element::string) { + isc_throw(DhcpConfigError, "realm is must be a string (" + << realm->getPosition() << ")"); + } + setRealm(realm->stringValue()); + } + + // Get user context + ConstElementPtr user_context_cfg = config->get("user-context"); + if (user_context_cfg) { + if (user_context_cfg->getType() != Element::map) { + isc_throw(DhcpConfigError, "user-context must be a map (" + << user_context_cfg->getPosition() << ")"); + } + setContext(user_context_cfg); + } + + // Get clients. + ConstElementPtr clients = config->get("clients"); + if (!clients) { + return; + } + if (clients->getType() != Element::list) { + isc_throw(DhcpConfigError, "clients must be a list (" + << clients->getPosition() << ")"); + } + + // Iterate on clients. + for (auto client : clients->listValue()) { if (client->getType() != Element::map) { - isc_throw(DhcpConfigError, "basic-authentications items must be " - << "maps (" << client->getPosition() << ")"); + isc_throw(DhcpConfigError, "clients items must be maps (" + << client->getPosition() << ")"); } // user ConstElementPtr user_cfg = client->get("user"); if (!user_cfg) { - isc_throw(DhcpConfigError, "user is required in " - << "basic-authentications items (" + isc_throw(DhcpConfigError, "user is required in clients items (" << client->getPosition() << ")"); } if (user_cfg->getType() != Element::string) { @@ -133,5 +200,60 @@ BasicHttpAuthConfig::parse(const ConstElementPtr& config) { } } +HttpResponseJsonPtr +BasicHttpAuthConfig::checkAuth(const HttpResponseCreator& creator, + const ConstHttpRequestPtr& request) const { + const BasicHttpAuthMap& credentials = getCredentialMap(); + bool authentic = false; + if (credentials.empty()) { + authentic = true; + } else try { + string value = request->getHeaderValue("Authorization"); + // Trim space characters. + value = str::trim(value); + if (value.size() < 8) { + isc_throw(BadValue, "header content is too short"); + } + // Get the authentication scheme which must be "basic". + string scheme = value.substr(0, 5); + str::lowercase(scheme); + if (scheme != "basic") { + isc_throw(BadValue, "not basic authentication"); + } + // Skip the authentication scheme name and space characters. + value = value.substr(5); + value = str::trim(value); + // Verify the credential is in the list. + const auto it = credentials.find(value); + if (it != credentials.end()) { + LOG_DEBUG(http_logger, isc::log::DBGLVL_TRACE_BASIC, + HTTP_CLIENT_REQUEST_AUTHORIZED) + .arg(it->second); + authentic = true; + } else { + LOG_INFO(http_logger, HTTP_CLIENT_REQUEST_NOT_AUTHORIZED); + authentic = false; + } + } 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()); + } + const string& realm = getRealm(); + const string& scheme = "Basic"; + HttpResponsePtr response = + creator.createStockHttpResponse(request, HttpStatusCode::UNAUTHORIZED); + response->reset(); + response->context()->headers_.push_back( + HttpHeaderContext("WWW-Authenticate", + scheme + " realm=\"" + realm + "\"")); + response->finalize(); + return (boost::dynamic_pointer_cast(response)); +} + } // end of namespace isc::http } // end of namespace isc diff --git a/src/lib/http/basic_auth_config.h b/src/lib/http/basic_auth_config.h index c459ba3c57..78d541061b 100644 --- a/src/lib/http/basic_auth_config.h +++ b/src/lib/http/basic_auth_config.h @@ -7,10 +7,7 @@ #ifndef HTTP_BASIC_AUTH_CONFIG_H #define HTTP_BASIC_AUTH_CONFIG_H -#include -#include -#include -#include +#include #include #include #include @@ -67,9 +64,12 @@ private: typedef std::list BasicHttpAuthClientList; /// @brief Basic HTTP authentication configuration. -class BasicHttpAuthConfig : public isc::data::CfgToElement { +class BasicHttpAuthConfig : public HttpAuthConfig { public: + /// @brief Destructor. + virtual ~BasicHttpAuthConfig() { } + /// @brief Add a client configuration. /// /// @param user User id @@ -80,8 +80,13 @@ public: const std::string& password, const isc::data::ConstElementPtr& user_context = isc::data::ConstElementPtr()); + /// @brief Empty predicate. + /// @return true if the configuration is empty so authentication + /// is not required. + virtual bool empty() const; + /// @brief Clear configuration. - void clear(); + virtual void clear(); /// @brief Returns the list of client configuration. /// @@ -109,6 +114,15 @@ public: /// @return A pointer to unparsed basic HTTP authentication configuration. virtual isc::data::ElementPtr toElement() const; + /// @brief Validate HTTP request. + /// + /// @param creator The HTTP response creator. + /// @param request The HTTP request to validate. + /// @return Error HTTP response if validation failed, null otherwise. + virtual isc::http::HttpResponseJsonPtr + checkAuth(const isc::http::HttpResponseCreator& creator, + const isc::http::ConstHttpRequestPtr& request) const; + private: /// @brief The list of basic HTTP authentication client configuration. @@ -118,6 +132,9 @@ private: BasicHttpAuthMap map_; }; +/// @brief Type of shared pointers to basic HTTP authentication configuration. +typedef boost::shared_ptr BasicHttpAuthConfigPtr; + } // end of namespace isc::http } // end of namespace isc diff --git a/src/lib/http/response_creator_auth.cc b/src/lib/http/response_creator_auth.cc deleted file mode 100644 index 4a19c14008..0000000000 --- a/src/lib/http/response_creator_auth.cc +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright (C) 2020 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#include - -#include -#include -#include - -using namespace isc; -using namespace isc::util; -using namespace std; - -namespace isc { -namespace http { - -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); - if (value.size() < 8) { - isc_throw(BadValue, "header content is too short"); - } - // Get the authentication scheme which must be "basic". - string scheme = value.substr(0, 5); - str::lowercase(scheme); - if (scheme != "basic") { - isc_throw(BadValue, "not basic authentication"); - } - // Skip the authentication scheme name and space characters. - value = value.substr(5); - value = str::trim(value); - // Verify the credential is in the list. - const auto it = credentials.find(value); - if (it != credentials.end()) { - LOG_DEBUG(http_logger, isc::log::DBGLVL_TRACE_BASIC, - HTTP_CLIENT_REQUEST_AUTHORIZED) - .arg(it->second); - authentic = true; - } else { - LOG_INFO(http_logger, HTTP_CLIENT_REQUEST_NOT_AUTHORIZED); - authentic = false; - } - } 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", - scheme + " realm=\"" + realm + "\"")); - response->finalize(); - return (boost::dynamic_pointer_cast(response)); -} - -} // end of namespace isc::http -} // end of namespace isc diff --git a/src/lib/http/response_creator_auth.h b/src/lib/http/response_creator_auth.h deleted file mode 100644 index 26e1c1aca3..0000000000 --- a/src/lib/http/response_creator_auth.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (C) 2020 Internet Systems Consortium, Inc. ("ISC") -// -// This Source Code Form is subject to the terms of the Mozilla Public -// License, v. 2.0. If a copy of the MPL was not distributed with this -// file, You can obtain one at http://mozilla.org/MPL/2.0/. - -#ifndef HTTP_RESPONSE_CREATOR_AUTH_H -#define HTTP_RESPONSE_CREATOR_AUTH_H - -#include -#include -#include -#include -#include - -namespace isc { -namespace http { - -/// @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 checkAuth(const HttpResponseCreator& creator, - const ConstHttpRequestPtr& request, - const BasicHttpAuthMap& credentials, - const std::string& realm); - -} // end of namespace isc::http -} // end of namespace isc - -#endif // endif HTTP_RESPONSE_CREATOR_AUTH_H diff --git a/src/lib/http/tests/basic_auth_config_unittests.cc b/src/lib/http/tests/basic_auth_config_unittests.cc index 5b7cd8605f..5a3f121d3b 100644 --- a/src/lib/http/tests/basic_auth_config_unittests.cc +++ b/src/lib/http/tests/basic_auth_config_unittests.cc @@ -44,15 +44,26 @@ TEST(BasicHttpAuthConfigTest, basic) { BasicHttpAuthConfig config; // Initial configuration is empty. + EXPECT_TRUE(config.empty()); + EXPECT_TRUE(config.getRealm().empty()); EXPECT_TRUE(config.getClientList().empty()); EXPECT_TRUE(config.getCredentialMap().empty()); + // Set the realm and user context. + EXPECT_NO_THROW(config.setRealm("my-realm")); + EXPECT_EQ("my-realm", config.getRealm()); + ConstElementPtr horse = Element::fromJSON("{ \"value\": \"a horse\" }"); + EXPECT_NO_THROW(config.setContext(horse)); + EXPECT_TRUE(horse->equals(*config.getContext())); + // Add rejects user id with embedded ':'. EXPECT_THROW(config.add("foo:", "bar"), BadValue); // Add a client. + EXPECT_TRUE(config.empty()); ConstElementPtr ctx = Element::fromJSON("{ \"foo\": \"bar\" }"); EXPECT_NO_THROW(config.add("foo", "bar", ctx)); + EXPECT_FALSE(config.empty()); // Check the client. ASSERT_EQ(1, config.getClientList().size()); @@ -68,12 +79,17 @@ TEST(BasicHttpAuthConfigTest, basic) { EXPECT_EQ("foo", user); // Check toElement. - ElementPtr expected = Element::createList(); + ElementPtr expected = Element::createMap(); + ElementPtr clients = Element::createList(); ElementPtr elem = Element::createMap(); elem->set("user", Element::create(string("foo"))); elem->set("password", Element::create(string("bar"))); elem->set("user-context", ctx); - expected->add(elem); + clients->add(elem); + expected->set("type", Element::create(string("basic"))); + expected->set("realm", Element::create(string("my-realm"))); + expected->set("user-context", horse); + expected->set("clients", clients); runToElementTest(expected, config); // Add a second client and test it. @@ -85,7 +101,8 @@ TEST(BasicHttpAuthConfigTest, basic) { // Check clear. config.clear(); - expected = Element::createList(); + EXPECT_TRUE(config.empty()); + expected->set("clients", Element::createList()); runToElementTest(expected, config); // Add clients again. @@ -96,8 +113,10 @@ TEST(BasicHttpAuthConfigTest, basic) { ElementPtr elem0 = Element::createMap(); elem0->set("user", Element::create(string("test"))); elem0->set("password", Element::create(string("123\xa3"))); - expected->add(elem0); - expected->add(elem); + clients = Element::createList(); + clients->add(elem0); + clients->add(elem); + expected->set("clients", clients); runToElementTest(expected, config); } @@ -108,35 +127,83 @@ TEST(BasicHttpAuthConfigTest, parse) { // No config is accepted. EXPECT_NO_THROW(config.parse(cfg)); + EXPECT_TRUE(config.empty()); EXPECT_TRUE(config.getClientList().empty()); EXPECT_TRUE(config.getCredentialMap().empty()); - runToElementTest(Element::createList(), config); + ElementPtr expected = Element::createMap(); + expected->set("type", Element::create(string("basic"))); + expected->set("realm", Element::create(string(""))); + expected->set("clients", Element::createList()); + runToElementTest(expected, config); - // The config must be a list. + // The config must be a map. + cfg = Element::createList(); + EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError, + "authentication must be a map (:0:0)"); + + // The type must be present. cfg = Element::createMap(); EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError, - "basic-authentications must be a list (:0:0)"); + "type is required in authentication (:0:0)"); + + // The type must be a string. + cfg->set("type", Element::create(true)); + EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError, + "type is must be a string (:0:0)"); + + // The type must be basic. + cfg->set("type", Element::create(string("foobar"))); + string errmsg = "only basic HTTP authentication is supported: type is "; + errmsg += "'foobar' not 'basic' (:0:0)"; + EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError, errmsg); + cfg->set("type", Element::create(string("basic"))); + EXPECT_NO_THROW(config.parse(cfg)); + + // The realm must be a string. + cfg->set("realm", Element::createList()); + EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError, + "realm is must be a string (:0:0)"); + cfg->set("realm", Element::create(string("my-realm"))); + EXPECT_NO_THROW(config.parse(cfg)); + + // The user context must be a map. + ElementPtr ctx = Element::createList(); + cfg->set("user-context", ctx); + EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError, + "user-context must be a map (:0:0)"); + ctx = Element::fromJSON("{ \"value\": \"a horse\" }"); + cfg->set("user-context", ctx); + EXPECT_NO_THROW(config.parse(cfg)); + + // Clients must be a list. + ElementPtr clients_cfg = Element::createMap(); + cfg->set("clients", clients_cfg); + EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError, + "clients must be a list (:0:0)"); // The client config must be a map. - cfg = Element::createList(); + clients_cfg = Element::createList(); ElementPtr client_cfg = Element::createList(); - cfg->add(client_cfg); + clients_cfg->add(client_cfg); + cfg->set("clients", clients_cfg); EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError, - "basic-authentications items must be maps (:0:0)"); + "clients items must be maps (:0:0)"); // The user parameter is mandatory in client config. client_cfg = Element::createMap(); - cfg = Element::createList(); - cfg->add(client_cfg); + clients_cfg = Element::createList(); + clients_cfg->add(client_cfg); + cfg->set("clients", clients_cfg); EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError, - "user is required in basic-authentications items (:0:0)"); + "user is required in clients items (:0:0)"); // The user parameter must be a string. ElementPtr user_cfg = Element::create(1); client_cfg = Element::createMap(); client_cfg->set("user", user_cfg); - cfg = Element::createList(); - cfg->add(client_cfg); + clients_cfg = Element::createList(); + clients_cfg->add(client_cfg); + cfg->set("clients", clients_cfg); EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError, "user must be a string (:0:0)"); @@ -144,8 +211,9 @@ TEST(BasicHttpAuthConfigTest, parse) { user_cfg = Element::create(string("")); client_cfg = Element::createMap(); client_cfg->set("user", user_cfg); - cfg = Element::createList(); - cfg->add(client_cfg); + clients_cfg = Element::createList(); + clients_cfg->add(client_cfg); + cfg->set("clients", clients_cfg); EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError, "user must be not be empty (:0:0)"); @@ -153,8 +221,9 @@ TEST(BasicHttpAuthConfigTest, parse) { user_cfg = Element::create(string("foo:bar")); client_cfg = Element::createMap(); client_cfg->set("user", user_cfg); - cfg = Element::createList(); - cfg->add(client_cfg); + clients_cfg = Element::createList(); + clients_cfg->add(client_cfg); + cfg->set("clients", clients_cfg); EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError, "user must not contain a ':': 'foo:bar' (:0:0)"); @@ -162,8 +231,9 @@ TEST(BasicHttpAuthConfigTest, parse) { user_cfg = Element::create(string("foo")); client_cfg = Element::createMap(); client_cfg->set("user", user_cfg); - cfg = Element::createList(); - cfg->add(client_cfg); + clients_cfg = Element::createList(); + clients_cfg->add(client_cfg); + cfg->set("clients", clients_cfg); EXPECT_NO_THROW(config.parse(cfg)); ASSERT_EQ(1, config.getClientList().size()); EXPECT_EQ("", config.getClientList().front().getPassword()); @@ -174,8 +244,9 @@ TEST(BasicHttpAuthConfigTest, parse) { client_cfg = Element::createMap(); client_cfg->set("user", user_cfg); client_cfg->set("password", password_cfg); - cfg = Element::createList(); - cfg->add(client_cfg); + clients_cfg = Element::createList(); + clients_cfg->add(client_cfg); + cfg->set("clients", clients_cfg); EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError, "password must be a string (:0:0)"); @@ -184,8 +255,9 @@ TEST(BasicHttpAuthConfigTest, parse) { client_cfg = Element::createMap(); client_cfg->set("user", user_cfg); client_cfg->set("password", password_cfg); - cfg = Element::createList(); - cfg->add(client_cfg); + clients_cfg = Element::createList(); + clients_cfg->add(client_cfg); + cfg->set("clients", clients_cfg); EXPECT_NO_THROW(config.parse(cfg)); ASSERT_EQ(1, config.getClientList().size()); EXPECT_EQ("", config.getClientList().front().getPassword()); @@ -193,13 +265,14 @@ TEST(BasicHttpAuthConfigTest, parse) { // User context must be a map. password_cfg = Element::create(string("bar")); - ElementPtr ctx = Element::createList(); + ctx = Element::createList(); client_cfg = Element::createMap(); client_cfg->set("user", user_cfg); client_cfg->set("password", password_cfg); client_cfg->set("user-context", ctx); - cfg = Element::createList(); - cfg->add(client_cfg); + clients_cfg = Element::createList(); + clients_cfg->add(client_cfg); + cfg->set("clients", clients_cfg); EXPECT_THROW_MSG(config.parse(cfg), DhcpConfigError, "user-context must be a map (:0:0)"); @@ -209,8 +282,9 @@ TEST(BasicHttpAuthConfigTest, parse) { client_cfg->set("user", user_cfg); client_cfg->set("password", password_cfg); client_cfg->set("user-context", ctx); - cfg = Element::createList(); - cfg->add(client_cfg); + clients_cfg = Element::createList(); + clients_cfg->add(client_cfg); + cfg->set("clients", clients_cfg); EXPECT_NO_THROW(config.parse(cfg)); runToElementTest(cfg, config); } diff --git a/src/lib/http/tests/response_creator_unittests.cc b/src/lib/http/tests/response_creator_unittests.cc index 35836c22eb..1b2f9fdfb8 100644 --- a/src/lib/http/tests/response_creator_unittests.cc +++ b/src/lib/http/tests/response_creator_unittests.cc @@ -6,11 +6,11 @@ #include #include +#include #include #include #include #include -#include #include #include #include @@ -140,13 +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 basic HTTP authentication configuration. + BasicHttpAuthConfigPtr auth_config(new BasicHttpAuthConfig()); + EXPECT_NO_THROW(auth_config->add("test", "123\xa3")); + const BasicHttpAuthMap& credentials = auth_config->getCredentialMap(); + auto cred = credentials.find("dGVzdDoxMjPCow=="); + EXPECT_NE(cred, credentials.end()); + EXPECT_EQ(cred->second, "test"); + auth_config->setRealm("ISC.ORG"); // Create request and finalize it. HttpRequestPtr request(new HttpRequest()); @@ -158,7 +159,7 @@ TEST_F(HttpResponseCreatorAuthTest, noAuth) { HttpResponsePtr response; TestHttpResponseCreatorPtr creator(new TestHttpResponseCreator());; - ASSERT_NO_THROW(response = checkAuth(*creator, request, credentials, realm)); + ASSERT_NO_THROW(response = auth_config->checkAuth(*creator, request)); ASSERT_TRUE(response); EXPECT_EQ("HTTP/1.0 401 Unauthorized\r\n" @@ -176,13 +177,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 basic HTTP authentication configuration. + BasicHttpAuthConfigPtr auth_config(new BasicHttpAuthConfig()); + EXPECT_NO_THROW(auth_config->add("test", "123\xa3")); + const BasicHttpAuthMap& credentials = auth_config->getCredentialMap(); + auto cred = credentials.find("dGVzdDoxMjPCow=="); + EXPECT_NE(cred, credentials.end()); + EXPECT_EQ(cred->second, "test"); + auth_config->setRealm("ISC.ORG"); // Create request and finalize it. HttpRequestPtr request(new HttpRequest()); @@ -196,7 +198,7 @@ TEST_F(HttpResponseCreatorAuthTest, authTooShort) { HttpResponsePtr response; TestHttpResponseCreatorPtr creator(new TestHttpResponseCreator());; - ASSERT_NO_THROW(response = checkAuth(*creator, request, credentials, realm)); + ASSERT_NO_THROW(response = auth_config->checkAuth(*creator, request)); ASSERT_TRUE(response); EXPECT_EQ("HTTP/1.0 401 Unauthorized\r\n" @@ -215,13 +217,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 basic HTTP authentication configuration. + BasicHttpAuthConfigPtr auth_config(new BasicHttpAuthConfig()); + EXPECT_NO_THROW(auth_config->add("test", "123\xa3")); + const BasicHttpAuthMap& credentials = auth_config->getCredentialMap(); + auto cred = credentials.find("dGVzdDoxMjPCow=="); + EXPECT_NE(cred, credentials.end()); + EXPECT_EQ(cred->second, "test"); + auth_config->setRealm("ISC.ORG"); // Create request and finalize it. HttpRequestPtr request(new HttpRequest()); @@ -235,7 +238,7 @@ TEST_F(HttpResponseCreatorAuthTest, badScheme) { HttpResponsePtr response; TestHttpResponseCreatorPtr creator(new TestHttpResponseCreator());; - ASSERT_NO_THROW(response = checkAuth(*creator, request, credentials, realm)); + ASSERT_NO_THROW(response = auth_config->checkAuth(*creator, request)); ASSERT_TRUE(response); EXPECT_EQ("HTTP/1.0 401 Unauthorized\r\n" @@ -254,13 +257,14 @@ 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 basic HTTP authentication configuration. + BasicHttpAuthConfigPtr auth_config(new BasicHttpAuthConfig()); + EXPECT_NO_THROW(auth_config->add("test", "123\xa3")); + const BasicHttpAuthMap& credentials = auth_config->getCredentialMap(); + auto cred = credentials.find("dGVzdDoxMjPCow=="); + EXPECT_NE(cred, credentials.end()); + EXPECT_EQ(cred->second, "test"); + auth_config->setRealm("ISC.ORG"); // Create request and finalize it. HttpRequestPtr request(new HttpRequest()); @@ -275,7 +279,7 @@ TEST_F(HttpResponseCreatorAuthTest, notMatching) { HttpResponsePtr response; TestHttpResponseCreatorPtr creator(new TestHttpResponseCreator());; - ASSERT_NO_THROW(response = checkAuth(*creator, request, credentials, realm)); + ASSERT_NO_THROW(response = auth_config->checkAuth(*creator, request)); ASSERT_TRUE(response); EXPECT_EQ("HTTP/1.0 401 Unauthorized\r\n" @@ -293,13 +297,14 @@ 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 basic HTTP authentication configuration. + BasicHttpAuthConfigPtr auth_config(new BasicHttpAuthConfig()); + EXPECT_NO_THROW(auth_config->add("test", "123\xa3")); + const BasicHttpAuthMap& credentials = auth_config->getCredentialMap(); + auto cred = credentials.find("dGVzdDoxMjPCow=="); + EXPECT_NE(cred, credentials.end()); + EXPECT_EQ(cred->second, "test"); + auth_config->setRealm("ISC.ORG"); // Create request and finalize it. HttpRequestPtr request(new HttpRequest()); @@ -307,13 +312,13 @@ TEST_F(HttpResponseCreatorAuthTest, matching) { request->context()->http_version_minor_ = 0; request->context()->method_ = "GET"; request->context()->uri_ = "/foo"; - BasicAuthHttpHeaderContext auth(*basic_auth); + HttpHeaderContext auth("Authorization", "Basic dGVzdDoxMjPCow=="); request->context()->headers_.push_back(auth); ASSERT_NO_THROW(request->finalize()); HttpResponsePtr response; TestHttpResponseCreatorPtr creator(new TestHttpResponseCreator());; - ASSERT_NO_THROW(response = checkAuth(*creator, request, credentials, realm)); + ASSERT_NO_THROW(response = auth_config->checkAuth(*creator, request)); EXPECT_FALSE(response); addString("HTTP_CLIENT_REQUEST_AUTHORIZED received HTTP request " -- GitLab From 9960b6e948a97fd5253fd63bc94dab3263e58e9b Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Sun, 13 Sep 2020 20:03:07 +0000 Subject: [PATCH 26/33] [#1304] regen files --- src/bin/agent/agent_lexer.cc | 118 ++++----- src/bin/agent/agent_parser.cc | 451 +++++++++++++++++----------------- src/bin/agent/agent_parser.h | 6 +- src/bin/agent/location.hh | 2 +- src/bin/agent/position.hh | 2 +- src/bin/agent/stack.hh | 2 +- 6 files changed, 294 insertions(+), 287 deletions(-) diff --git a/src/bin/agent/agent_lexer.cc b/src/bin/agent/agent_lexer.cc index 07d4b7ddce..da5db397fe 100644 --- a/src/bin/agent/agent_lexer.cc +++ b/src/bin/agent/agent_lexer.cc @@ -1409,12 +1409,12 @@ int yy_flex_debug = 1; static const flex_int16_t yy_rule_linenum[62] = { 0, 133, 135, 137, 142, 143, 148, 149, 150, 162, 165, - 170, 177, 186, 195, 204, 216, 228, 237, 246, 255, - 264, 273, 282, 291, 300, 309, 318, 327, 336, 345, - 354, 363, 372, 381, 390, 399, 408, 417, 426, 435, - 444, 453, 462, 471, 570, 575, 580, 585, 586, 587, - 588, 589, 590, 592, 610, 623, 628, 632, 634, 636, - 638 + 170, 177, 186, 195, 204, 217, 230, 239, 248, 257, + 266, 275, 284, 293, 302, 311, 320, 329, 338, 347, + 356, 365, 374, 383, 392, 401, 410, 419, 428, 437, + 446, 455, 464, 473, 572, 577, 582, 587, 588, 589, + 590, 591, 592, 594, 612, 625, 630, 634, 636, 638, + 640 } ; /* The intent behind this definition is that it'll catch @@ -2016,9 +2016,10 @@ YY_RULE_SETUP { switch(driver.ctx_) { case ParserContext::AGENT: + case ParserContext::AUTHENTICATION; + case ParserContext::CLIENTS: case ParserContext::SERVER: case ParserContext::LOGGERS: - case ParserContext::CLIENTS: return AgentParser::make_USER_CONTEXT(driver.loc_); default: return AgentParser::make_STRING("user-context", driver.loc_); @@ -2027,13 +2028,14 @@ YY_RULE_SETUP YY_BREAK case 16: YY_RULE_SETUP -#line 216 "agent_lexer.ll" +#line 217 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::AGENT: + case ParserContext::AUTHENTICATION; + case ParserContext::CLIENTS: case ParserContext::SERVER: case ParserContext::LOGGERS: - case ParserContext::CLIENTS: return AgentParser::make_COMMENT(driver.loc_); default: return AgentParser::make_STRING("comment", driver.loc_); @@ -2042,7 +2044,7 @@ YY_RULE_SETUP YY_BREAK case 17: YY_RULE_SETUP -#line 228 "agent_lexer.ll" +#line 230 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::AGENT: @@ -2054,7 +2056,7 @@ YY_RULE_SETUP YY_BREAK case 18: YY_RULE_SETUP -#line 237 "agent_lexer.ll" +#line 239 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::AUTHENTICATION: @@ -2066,7 +2068,7 @@ YY_RULE_SETUP YY_BREAK case 19: YY_RULE_SETUP -#line 246 "agent_lexer.ll" +#line 248 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::AUTH_TYPE: @@ -2078,7 +2080,7 @@ YY_RULE_SETUP YY_BREAK case 20: YY_RULE_SETUP -#line 255 "agent_lexer.ll" +#line 257 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::AUTHENTICATION: @@ -2090,7 +2092,7 @@ YY_RULE_SETUP YY_BREAK case 21: YY_RULE_SETUP -#line 264 "agent_lexer.ll" +#line 266 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::AUTHENTICATION: @@ -2102,7 +2104,7 @@ YY_RULE_SETUP YY_BREAK case 22: YY_RULE_SETUP -#line 273 "agent_lexer.ll" +#line 275 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::CLIENTS: @@ -2114,7 +2116,7 @@ YY_RULE_SETUP YY_BREAK case 23: YY_RULE_SETUP -#line 282 "agent_lexer.ll" +#line 284 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::CLIENTS: @@ -2126,7 +2128,7 @@ YY_RULE_SETUP YY_BREAK case 24: YY_RULE_SETUP -#line 291 "agent_lexer.ll" +#line 293 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::AGENT: @@ -2138,7 +2140,7 @@ YY_RULE_SETUP YY_BREAK case 25: YY_RULE_SETUP -#line 300 "agent_lexer.ll" +#line 302 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::CONTROL_SOCKETS: @@ -2150,7 +2152,7 @@ YY_RULE_SETUP YY_BREAK case 26: YY_RULE_SETUP -#line 309 "agent_lexer.ll" +#line 311 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::CONTROL_SOCKETS: @@ -2162,7 +2164,7 @@ YY_RULE_SETUP YY_BREAK case 27: YY_RULE_SETUP -#line 318 "agent_lexer.ll" +#line 320 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::CONTROL_SOCKETS: @@ -2174,7 +2176,7 @@ YY_RULE_SETUP YY_BREAK case 28: YY_RULE_SETUP -#line 327 "agent_lexer.ll" +#line 329 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::SERVER: @@ -2186,7 +2188,7 @@ YY_RULE_SETUP YY_BREAK case 29: YY_RULE_SETUP -#line 336 "agent_lexer.ll" +#line 338 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::SERVER: @@ -2198,7 +2200,7 @@ YY_RULE_SETUP YY_BREAK case 30: YY_RULE_SETUP -#line 345 "agent_lexer.ll" +#line 347 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::SOCKET_TYPE: @@ -2210,7 +2212,7 @@ YY_RULE_SETUP YY_BREAK case 31: YY_RULE_SETUP -#line 354 "agent_lexer.ll" +#line 356 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::AGENT: @@ -2222,7 +2224,7 @@ YY_RULE_SETUP YY_BREAK case 32: YY_RULE_SETUP -#line 363 "agent_lexer.ll" +#line 365 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::HOOKS_LIBRARIES: @@ -2234,7 +2236,7 @@ YY_RULE_SETUP YY_BREAK case 33: YY_RULE_SETUP -#line 372 "agent_lexer.ll" +#line 374 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::HOOKS_LIBRARIES: @@ -2246,7 +2248,7 @@ YY_RULE_SETUP YY_BREAK case 34: YY_RULE_SETUP -#line 381 "agent_lexer.ll" +#line 383 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::AGENT: @@ -2258,7 +2260,7 @@ YY_RULE_SETUP YY_BREAK case 35: YY_RULE_SETUP -#line 390 "agent_lexer.ll" +#line 392 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::LOGGERS: @@ -2270,7 +2272,7 @@ YY_RULE_SETUP YY_BREAK case 36: YY_RULE_SETUP -#line 399 "agent_lexer.ll" +#line 401 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::LOGGERS: @@ -2282,7 +2284,7 @@ YY_RULE_SETUP YY_BREAK case 37: YY_RULE_SETUP -#line 408 "agent_lexer.ll" +#line 410 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::OUTPUT_OPTIONS: @@ -2294,7 +2296,7 @@ YY_RULE_SETUP YY_BREAK case 38: YY_RULE_SETUP -#line 417 "agent_lexer.ll" +#line 419 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::OUTPUT_OPTIONS: @@ -2306,7 +2308,7 @@ YY_RULE_SETUP YY_BREAK case 39: YY_RULE_SETUP -#line 426 "agent_lexer.ll" +#line 428 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::OUTPUT_OPTIONS: @@ -2318,7 +2320,7 @@ YY_RULE_SETUP YY_BREAK case 40: YY_RULE_SETUP -#line 435 "agent_lexer.ll" +#line 437 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::OUTPUT_OPTIONS: @@ -2330,7 +2332,7 @@ YY_RULE_SETUP YY_BREAK case 41: YY_RULE_SETUP -#line 444 "agent_lexer.ll" +#line 446 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::OUTPUT_OPTIONS: @@ -2342,7 +2344,7 @@ YY_RULE_SETUP YY_BREAK case 42: YY_RULE_SETUP -#line 453 "agent_lexer.ll" +#line 455 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::LOGGERS: @@ -2354,7 +2356,7 @@ YY_RULE_SETUP YY_BREAK case 43: YY_RULE_SETUP -#line 462 "agent_lexer.ll" +#line 464 "agent_lexer.ll" { switch(driver.ctx_) { case ParserContext::LOGGERS: @@ -2366,7 +2368,7 @@ YY_RULE_SETUP YY_BREAK case 44: YY_RULE_SETUP -#line 471 "agent_lexer.ll" +#line 473 "agent_lexer.ll" { /* A string has been matched. It contains the actual string and single quotes. We need to get those quotes out of the way and just use its content, e.g. @@ -2469,7 +2471,7 @@ YY_RULE_SETUP case 45: /* rule 45 can match eol */ YY_RULE_SETUP -#line 570 "agent_lexer.ll" +#line 572 "agent_lexer.ll" { /* Bad string with a forbidden control character inside */ driver.error(driver.loc_, "Invalid control in " + std::string(yytext)); @@ -2478,7 +2480,7 @@ YY_RULE_SETUP case 46: /* rule 46 can match eol */ YY_RULE_SETUP -#line 575 "agent_lexer.ll" +#line 577 "agent_lexer.ll" { /* Bad string with a bad escape inside */ driver.error(driver.loc_, "Bad escape in " + std::string(yytext)); @@ -2486,7 +2488,7 @@ YY_RULE_SETUP YY_BREAK case 47: YY_RULE_SETUP -#line 580 "agent_lexer.ll" +#line 582 "agent_lexer.ll" { /* Bad string with an open escape at the end */ driver.error(driver.loc_, "Overflow escape in " + std::string(yytext)); @@ -2494,37 +2496,37 @@ YY_RULE_SETUP YY_BREAK case 48: YY_RULE_SETUP -#line 585 "agent_lexer.ll" +#line 587 "agent_lexer.ll" { return AgentParser::make_LSQUARE_BRACKET(driver.loc_); } YY_BREAK case 49: YY_RULE_SETUP -#line 586 "agent_lexer.ll" +#line 588 "agent_lexer.ll" { return AgentParser::make_RSQUARE_BRACKET(driver.loc_); } YY_BREAK case 50: YY_RULE_SETUP -#line 587 "agent_lexer.ll" +#line 589 "agent_lexer.ll" { return AgentParser::make_LCURLY_BRACKET(driver.loc_); } YY_BREAK case 51: YY_RULE_SETUP -#line 588 "agent_lexer.ll" +#line 590 "agent_lexer.ll" { return AgentParser::make_RCURLY_BRACKET(driver.loc_); } YY_BREAK case 52: YY_RULE_SETUP -#line 589 "agent_lexer.ll" +#line 591 "agent_lexer.ll" { return AgentParser::make_COMMA(driver.loc_); } YY_BREAK case 53: YY_RULE_SETUP -#line 590 "agent_lexer.ll" +#line 592 "agent_lexer.ll" { return AgentParser::make_COLON(driver.loc_); } YY_BREAK case 54: YY_RULE_SETUP -#line 592 "agent_lexer.ll" +#line 594 "agent_lexer.ll" { /* An integer was found. */ std::string tmp(yytext); @@ -2545,7 +2547,7 @@ YY_RULE_SETUP YY_BREAK case 55: YY_RULE_SETUP -#line 610 "agent_lexer.ll" +#line 612 "agent_lexer.ll" { /* A floating point was found. */ std::string tmp(yytext); @@ -2561,7 +2563,7 @@ YY_RULE_SETUP YY_BREAK case 56: YY_RULE_SETUP -#line 623 "agent_lexer.ll" +#line 625 "agent_lexer.ll" { string tmp(yytext); return AgentParser::make_BOOLEAN(tmp == "true", driver.loc_); @@ -2569,33 +2571,33 @@ YY_RULE_SETUP YY_BREAK case 57: YY_RULE_SETUP -#line 628 "agent_lexer.ll" +#line 630 "agent_lexer.ll" { return AgentParser::make_NULL_TYPE(driver.loc_); } YY_BREAK case 58: YY_RULE_SETUP -#line 632 "agent_lexer.ll" +#line 634 "agent_lexer.ll" driver.error (driver.loc_, "JSON true reserved keyword is lower case only"); YY_BREAK case 59: YY_RULE_SETUP -#line 634 "agent_lexer.ll" +#line 636 "agent_lexer.ll" driver.error (driver.loc_, "JSON false reserved keyword is lower case only"); YY_BREAK case 60: YY_RULE_SETUP -#line 636 "agent_lexer.ll" +#line 638 "agent_lexer.ll" driver.error (driver.loc_, "JSON null reserved keyword is lower case only"); YY_BREAK case 61: YY_RULE_SETUP -#line 638 "agent_lexer.ll" +#line 640 "agent_lexer.ll" driver.error (driver.loc_, "Invalid character: " + std::string(yytext)); YY_BREAK case YY_STATE_EOF(INITIAL): -#line 640 "agent_lexer.ll" +#line 642 "agent_lexer.ll" { if (driver.states_.empty()) { return AgentParser::make_END(driver.loc_); @@ -2621,10 +2623,10 @@ case YY_STATE_EOF(INITIAL): YY_BREAK case 62: YY_RULE_SETUP -#line 663 "agent_lexer.ll" +#line 665 "agent_lexer.ll" ECHO; YY_BREAK -#line 2627 "agent_lexer.cc" +#line 2629 "agent_lexer.cc" case YY_END_OF_BUFFER: { @@ -3729,7 +3731,7 @@ void yyfree (void * ptr ) /* %ok-for-header */ -#line 663 "agent_lexer.ll" +#line 665 "agent_lexer.ll" using namespace isc::dhcp; diff --git a/src/bin/agent/agent_parser.cc b/src/bin/agent/agent_parser.cc index ad0cdd029b..15a1f352e4 100644 --- a/src/bin/agent/agent_parser.cc +++ b/src/bin/agent/agent_parser.cc @@ -1241,8 +1241,8 @@ namespace isc { namespace agent { #line 1242 "agent_parser.cc" break; - case 106: // $@23: %empty -#line 518 "agent_parser.yy" + case 109: // $@23: %empty +#line 521 "agent_parser.yy" { // Add unique here ctx.enter(ctx.AUTH_TYPE); @@ -1250,8 +1250,8 @@ namespace isc { namespace agent { #line 1251 "agent_parser.cc" break; - case 107: // auth_type: "type" $@23 ":" auth_type_value -#line 521 "agent_parser.yy" + case 110: // auth_type: "type" $@23 ":" auth_type_value +#line 524 "agent_parser.yy" { ctx.stack_.back()->set("type", yystack_[0].value.as < ElementPtr > ()); ctx.leave(); @@ -1259,14 +1259,14 @@ namespace isc { namespace agent { #line 1260 "agent_parser.cc" break; - case 108: // auth_type_value: "basic" -#line 526 "agent_parser.yy" + case 111: // auth_type_value: "basic" +#line 529 "agent_parser.yy" { yylhs.value.as < ElementPtr > () = ElementPtr(new StringElement("basic", ctx.loc2pos(yystack_[0].location))); } #line 1266 "agent_parser.cc" break; - case 109: // $@24: %empty -#line 529 "agent_parser.yy" + case 112: // $@24: %empty +#line 532 "agent_parser.yy" { // Add unique here ctx.enter(ctx.NO_KEYWORDS); @@ -1274,8 +1274,8 @@ namespace isc { namespace agent { #line 1275 "agent_parser.cc" break; - case 110: // realm: "realm" $@24 ":" "constant string" -#line 532 "agent_parser.yy" + case 113: // realm: "realm" $@24 ":" "constant string" +#line 535 "agent_parser.yy" { ElementPtr realm(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("realm", realm); @@ -1284,8 +1284,8 @@ namespace isc { namespace agent { #line 1285 "agent_parser.cc" break; - case 111: // $@25: %empty -#line 538 "agent_parser.yy" + case 114: // $@25: %empty +#line 541 "agent_parser.yy" { // Add unique here ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location))); @@ -1296,8 +1296,8 @@ namespace isc { namespace agent { #line 1297 "agent_parser.cc" break; - case 112: // clients: "clients" $@25 ":" "[" clients_list "]" -#line 544 "agent_parser.yy" + case 115: // clients: "clients" $@25 ":" "[" clients_list "]" +#line 547 "agent_parser.yy" { ctx.stack_.pop_back(); ctx.leave(); @@ -1305,8 +1305,8 @@ namespace isc { namespace agent { #line 1306 "agent_parser.cc" break; - case 117: // $@26: %empty -#line 557 "agent_parser.yy" + case 120: // $@26: %empty +#line 560 "agent_parser.yy" { ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->add(m); @@ -1315,24 +1315,24 @@ namespace isc { namespace agent { #line 1316 "agent_parser.cc" break; - case 118: // basic_auth: "{" $@26 clients_params "}" -#line 561 "agent_parser.yy" + case 121: // basic_auth: "{" $@26 clients_params "}" +#line 564 "agent_parser.yy" { ctx.stack_.pop_back(); } #line 1324 "agent_parser.cc" break; - case 126: // $@27: %empty -#line 576 "agent_parser.yy" + case 129: // $@27: %empty +#line 579 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } #line 1332 "agent_parser.cc" break; - case 127: // user: "user" $@27 ":" "constant string" -#line 578 "agent_parser.yy" + case 130: // user: "user" $@27 ":" "constant string" +#line 581 "agent_parser.yy" { ElementPtr user(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("user", user); @@ -1341,16 +1341,16 @@ namespace isc { namespace agent { #line 1342 "agent_parser.cc" break; - case 128: // $@28: %empty -#line 584 "agent_parser.yy" + case 131: // $@28: %empty +#line 587 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } #line 1350 "agent_parser.cc" break; - case 129: // password: "password" $@28 ":" "constant string" -#line 586 "agent_parser.yy" + case 132: // password: "password" $@28 ":" "constant string" +#line 589 "agent_parser.yy" { ElementPtr password(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("password", password); @@ -1359,8 +1359,8 @@ namespace isc { namespace agent { #line 1360 "agent_parser.cc" break; - case 130: // $@29: %empty -#line 596 "agent_parser.yy" + case 133: // $@29: %empty +#line 599 "agent_parser.yy" { ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("loggers", l); @@ -1370,8 +1370,8 @@ namespace isc { namespace agent { #line 1371 "agent_parser.cc" break; - case 131: // loggers: "loggers" $@29 ":" "[" loggers_entries "]" -#line 601 "agent_parser.yy" + case 134: // loggers: "loggers" $@29 ":" "[" loggers_entries "]" +#line 604 "agent_parser.yy" { ctx.stack_.pop_back(); ctx.leave(); @@ -1379,8 +1379,8 @@ namespace isc { namespace agent { #line 1380 "agent_parser.cc" break; - case 134: // $@30: %empty -#line 613 "agent_parser.yy" + case 137: // $@30: %empty +#line 616 "agent_parser.yy" { ElementPtr l(new MapElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->add(l); @@ -1389,24 +1389,24 @@ namespace isc { namespace agent { #line 1390 "agent_parser.cc" break; - case 135: // logger_entry: "{" $@30 logger_params "}" -#line 617 "agent_parser.yy" + case 138: // logger_entry: "{" $@30 logger_params "}" +#line 620 "agent_parser.yy" { ctx.stack_.pop_back(); } #line 1398 "agent_parser.cc" break; - case 145: // $@31: %empty -#line 634 "agent_parser.yy" + case 148: // $@31: %empty +#line 637 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } #line 1406 "agent_parser.cc" break; - case 146: // name: "name" $@31 ":" "constant string" -#line 636 "agent_parser.yy" + case 149: // name: "name" $@31 ":" "constant string" +#line 639 "agent_parser.yy" { ElementPtr name(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("name", name); @@ -1415,8 +1415,8 @@ namespace isc { namespace agent { #line 1416 "agent_parser.cc" break; - case 147: // debuglevel: "debuglevel" ":" "integer" -#line 642 "agent_parser.yy" + case 150: // debuglevel: "debuglevel" ":" "integer" +#line 645 "agent_parser.yy" { ElementPtr dl(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("debuglevel", dl); @@ -1424,16 +1424,16 @@ namespace isc { namespace agent { #line 1425 "agent_parser.cc" break; - case 148: // $@32: %empty -#line 647 "agent_parser.yy" + case 151: // $@32: %empty +#line 650 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } #line 1433 "agent_parser.cc" break; - case 149: // severity: "severity" $@32 ":" "constant string" -#line 649 "agent_parser.yy" + case 152: // severity: "severity" $@32 ":" "constant string" +#line 652 "agent_parser.yy" { ElementPtr sev(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("severity", sev); @@ -1442,8 +1442,8 @@ namespace isc { namespace agent { #line 1443 "agent_parser.cc" break; - case 150: // $@33: %empty -#line 655 "agent_parser.yy" + case 153: // $@33: %empty +#line 658 "agent_parser.yy" { ElementPtr l(new ListElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("output_options", l); @@ -1453,8 +1453,8 @@ namespace isc { namespace agent { #line 1454 "agent_parser.cc" break; - case 151: // output_options_list: "output_options" $@33 ":" "[" output_options_list_content "]" -#line 660 "agent_parser.yy" + case 154: // output_options_list: "output_options" $@33 ":" "[" output_options_list_content "]" +#line 663 "agent_parser.yy" { ctx.stack_.pop_back(); ctx.leave(); @@ -1462,8 +1462,8 @@ namespace isc { namespace agent { #line 1463 "agent_parser.cc" break; - case 154: // $@34: %empty -#line 669 "agent_parser.yy" + case 157: // $@34: %empty +#line 672 "agent_parser.yy" { ElementPtr m(new MapElement(ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->add(m); @@ -1472,24 +1472,24 @@ namespace isc { namespace agent { #line 1473 "agent_parser.cc" break; - case 155: // output_entry: "{" $@34 output_params_list "}" -#line 673 "agent_parser.yy" + case 158: // output_entry: "{" $@34 output_params_list "}" +#line 676 "agent_parser.yy" { ctx.stack_.pop_back(); } #line 1481 "agent_parser.cc" break; - case 163: // $@35: %empty -#line 688 "agent_parser.yy" + case 166: // $@35: %empty +#line 691 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } #line 1489 "agent_parser.cc" break; - case 164: // output: "output" $@35 ":" "constant string" -#line 690 "agent_parser.yy" + case 167: // output: "output" $@35 ":" "constant string" +#line 693 "agent_parser.yy" { ElementPtr sev(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("output", sev); @@ -1498,8 +1498,8 @@ namespace isc { namespace agent { #line 1499 "agent_parser.cc" break; - case 165: // flush: "flush" ":" "boolean" -#line 696 "agent_parser.yy" + case 168: // flush: "flush" ":" "boolean" +#line 699 "agent_parser.yy" { ElementPtr flush(new BoolElement(yystack_[0].value.as < bool > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("flush", flush); @@ -1507,8 +1507,8 @@ namespace isc { namespace agent { #line 1508 "agent_parser.cc" break; - case 166: // maxsize: "maxsize" ":" "integer" -#line 701 "agent_parser.yy" + case 169: // maxsize: "maxsize" ":" "integer" +#line 704 "agent_parser.yy" { ElementPtr maxsize(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("maxsize", maxsize); @@ -1516,8 +1516,8 @@ namespace isc { namespace agent { #line 1517 "agent_parser.cc" break; - case 167: // maxver: "maxver" ":" "integer" -#line 706 "agent_parser.yy" + case 170: // maxver: "maxver" ":" "integer" +#line 709 "agent_parser.yy" { ElementPtr maxver(new IntElement(yystack_[0].value.as < int64_t > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("maxver", maxver); @@ -1525,16 +1525,16 @@ namespace isc { namespace agent { #line 1526 "agent_parser.cc" break; - case 168: // $@36: %empty -#line 711 "agent_parser.yy" + case 171: // $@36: %empty +#line 714 "agent_parser.yy" { ctx.enter(ctx.NO_KEYWORDS); } #line 1534 "agent_parser.cc" break; - case 169: // pattern: "pattern" $@36 ":" "constant string" -#line 713 "agent_parser.yy" + case 172: // pattern: "pattern" $@36 ":" "constant string" +#line 716 "agent_parser.yy" { ElementPtr sev(new StringElement(yystack_[0].value.as < std::string > (), ctx.loc2pos(yystack_[0].location))); ctx.stack_.back()->set("pattern", sev); @@ -1893,42 +1893,42 @@ namespace isc { namespace agent { } - const short AgentParser::yypact_ninf_ = -133; + const signed char AgentParser::yypact_ninf_ = -82; const signed char AgentParser::yytable_ninf_ = -1; const short AgentParser::yypact_[] = { - 59, -133, -133, -133, 8, 5, 6, 13, -133, -133, - -133, -133, -133, -133, -133, -133, -133, -133, -133, -133, - -133, -133, -133, -133, 5, -34, 18, 10, -133, 48, - 83, 58, 96, 102, -133, 98, -133, -133, -133, 104, - -133, -133, -133, 106, -133, -133, 107, -133, 1, -133, - -133, -133, -133, -133, -133, -133, -133, -133, -133, 5, - 5, -133, 70, 112, -133, 113, 72, 115, 116, 117, - 118, 119, 120, -133, 10, -133, -133, -133, 123, 121, - 88, -133, 122, 89, 124, -133, 125, 127, -133, 5, - 10, -133, -133, -133, -133, 80, -8, 128, 129, -133, - 28, -133, -133, -133, 73, -133, -133, -133, -133, -133, - -133, -133, -133, 74, -133, -133, -133, -133, -133, 131, - 135, -133, -133, 55, -133, -133, 136, 137, 138, 80, - -133, 139, 140, 141, -8, -133, -12, -133, 128, -7, - 129, -133, 105, 101, 134, -133, 142, 143, 144, -133, - -133, -133, -133, 75, -133, -133, -133, -133, -133, -133, - 148, -133, -133, -133, -133, 76, -133, -133, -133, -133, - -133, -133, -133, -133, -133, 146, 30, 30, 30, 150, - 151, 4, -133, 152, 153, 126, 154, -7, -133, -133, - 157, 145, -133, -133, -133, -133, -133, -133, 77, -133, - -133, -133, 84, 85, 114, 122, -133, 130, 159, -133, - 132, -133, 46, -133, 146, 161, 162, 30, -133, -133, - -133, -133, -133, -133, 160, -133, -133, -133, -133, -133, - -133, 86, -133, -133, -133, -133, 133, 155, -133, -133, - 94, -133, 164, 165, 46, -133, -133, -133, -133, 33, - 160, -133, 147, 149, -133, -133, 166, 167, 169, -133, - 87, -133, -133, -133, -133, -133, -133, -133, -133, -133, - 170, 99, 156, 158, 172, 33, -133, 163, -133, -133, - -133, 168, -133, -133, -133 + 60, -82, -82, -82, 4, 6, -1, 5, -82, -82, + -82, -82, -82, -82, -82, -82, -82, -82, -82, -82, + -82, -82, -82, -82, 6, -31, 8, 12, -82, 14, + 53, 63, 56, 70, -82, 87, -82, -82, -82, 105, + -82, -82, -82, 119, -82, -82, 120, -82, 2, -82, + -82, -82, -82, -82, -82, -82, -82, -82, -82, 6, + 6, -82, 85, 121, -82, 122, 51, 124, 125, 127, + 126, 128, 130, -82, 12, -82, -82, -82, 131, 129, + 92, -82, 132, 95, 134, -82, 133, 137, -82, 6, + 12, -82, -82, -82, -82, 3, 55, 136, 138, -82, + 27, -82, -82, -82, -82, -82, -82, 52, -82, -82, + -82, -82, -82, -82, -82, -82, 80, -82, -82, -82, + -82, -82, 140, 141, -82, -82, 108, -82, -82, 143, + 144, 145, 3, -82, 146, 147, 148, 55, -82, 31, + -82, 136, -5, 138, -82, 139, 109, 150, -82, 151, + 152, 153, -82, -82, -82, -82, 81, -82, -82, -82, + -82, -82, -82, 149, -82, -82, -82, -82, 82, -82, + -82, -82, -82, -82, -82, -82, -82, -82, 154, 32, + 32, 32, 158, 160, 89, -82, 163, 164, 111, 165, + -5, -82, -82, 166, 167, -82, -82, -82, -82, -82, + -82, 83, -82, -82, -82, 84, 90, 135, 132, -82, + 142, 168, -82, 155, -82, 61, -82, 154, 170, 171, + 32, -82, -82, -82, -82, -82, -82, 169, -82, -82, + -82, -82, -82, -82, 91, -82, -82, -82, -82, 156, + 157, -82, -82, 110, -82, 173, 174, 61, -82, -82, + -82, -82, -2, 169, -82, 159, 161, -82, -82, 175, + 177, 178, -82, 93, -82, -82, -82, -82, -82, -82, + -82, -82, -82, 179, 123, 162, 172, 180, -2, -82, + 176, -82, -82, -82, 181, -82, -82, -82 }; const unsigned char @@ -1938,117 +1938,119 @@ namespace isc { namespace agent { 18, 15, 14, 11, 12, 13, 3, 10, 16, 17, 32, 5, 8, 7, 27, 21, 0, 0, 29, 0, 28, 0, 0, 22, 36, 0, 34, 35, 49, 0, - 52, 54, 99, 0, 56, 130, 0, 48, 0, 38, + 52, 54, 99, 0, 56, 133, 0, 48, 0, 38, 40, 41, 46, 47, 44, 43, 42, 45, 26, 0, 0, 19, 0, 0, 33, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 9, 30, 23, 0, 0, 0, 51, 0, 0, 0, 73, 0, 0, 39, 0, 0, 50, 20, 53, 55, 0, 0, 58, 0, 24, - 0, 106, 109, 111, 0, 101, 103, 104, 105, 81, - 83, 85, 80, 0, 75, 77, 78, 79, 62, 0, - 59, 60, 134, 0, 132, 37, 0, 0, 0, 0, - 100, 0, 0, 0, 0, 74, 0, 57, 0, 0, - 0, 131, 0, 0, 0, 102, 0, 0, 0, 76, - 69, 71, 66, 0, 64, 67, 68, 61, 145, 150, - 0, 148, 144, 142, 143, 0, 136, 138, 140, 141, - 139, 133, 108, 107, 110, 113, 0, 0, 0, 0, - 0, 0, 63, 0, 0, 0, 0, 0, 135, 117, - 0, 114, 115, 94, 96, 93, 91, 92, 0, 87, - 89, 90, 0, 0, 0, 0, 65, 0, 0, 147, - 0, 137, 0, 112, 0, 0, 0, 0, 82, 84, - 86, 70, 72, 146, 0, 149, 126, 128, 125, 123, - 124, 0, 119, 121, 122, 116, 0, 0, 88, 154, - 0, 152, 0, 0, 0, 118, 95, 98, 97, 0, - 0, 151, 0, 0, 120, 163, 0, 0, 0, 168, - 0, 156, 158, 159, 160, 161, 162, 153, 127, 129, - 0, 0, 0, 0, 0, 0, 155, 0, 165, 166, - 167, 0, 157, 164, 169 + 0, 109, 112, 114, 108, 107, 106, 0, 101, 103, + 104, 105, 81, 83, 85, 80, 0, 75, 77, 78, + 79, 62, 0, 59, 60, 137, 0, 135, 37, 0, + 0, 0, 0, 100, 0, 0, 0, 0, 74, 0, + 57, 0, 0, 0, 134, 0, 0, 0, 102, 0, + 0, 0, 76, 69, 71, 66, 0, 64, 67, 68, + 61, 148, 153, 0, 151, 147, 145, 146, 0, 139, + 141, 143, 144, 142, 136, 111, 110, 113, 116, 0, + 0, 0, 0, 0, 0, 63, 0, 0, 0, 0, + 0, 138, 120, 0, 117, 118, 94, 96, 93, 91, + 92, 0, 87, 89, 90, 0, 0, 0, 0, 65, + 0, 0, 150, 0, 140, 0, 115, 0, 0, 0, + 0, 82, 84, 86, 70, 72, 149, 0, 152, 129, + 131, 128, 126, 127, 0, 122, 124, 125, 119, 0, + 0, 88, 157, 0, 155, 0, 0, 0, 121, 95, + 98, 97, 0, 0, 154, 0, 0, 123, 166, 0, + 0, 0, 171, 0, 159, 161, 162, 163, 164, 165, + 156, 130, 132, 0, 0, 0, 0, 0, 0, 158, + 0, 168, 169, 170, 0, 160, 167, 172 }; - const short + const signed char AgentParser::yypgoto_[] = { - -133, -133, -133, -133, -133, -133, -133, -133, -19, -79, - -133, -24, -133, -133, -133, -133, -133, -133, -27, -133, - -133, -133, -133, -133, -133, 90, 108, -133, -133, -133, - -26, -133, -25, -133, -133, -133, -133, -133, 41, -133, - -133, 3, -133, -133, -133, -133, -133, -133, -133, 54, - -133, -133, -133, -133, -133, -133, -132, -28, -133, -133, - -133, -133, -133, -133, -133, -133, 61, -133, -133, -133, - -133, -133, -133, -133, -133, -133, -23, -133, -133, -51, - -133, -133, -133, -133, -133, -133, -133, 56, -133, -133, - 11, -133, -133, -133, -133, -133, -133, -133, -133, -55, - -133, -133, -78, -133, -133, -133, -133, -133, -133, -133 + -82, -82, -82, -82, -82, -82, -82, -82, -17, -81, + -82, -22, -82, -82, -82, -82, -82, -82, -27, -82, + -82, -82, -82, -82, -82, 99, 118, -82, -82, -82, + -25, -82, -24, -82, -82, -82, -82, -82, 54, -82, + -82, 9, -82, -82, -82, -82, -82, -82, -82, 57, + -82, -82, -82, -82, -82, -82, -59, -23, -82, -82, + -82, -82, -82, -82, -82, -82, 64, -82, -82, -82, + -82, -82, -82, -82, -82, -82, -19, -82, -82, -48, + -82, -82, -82, -82, -82, -82, -82, 59, -82, -82, + 13, -82, -82, -82, -82, -82, -82, -82, -82, -46, + -82, -82, -73, -82, -82, -82, -82, -82, -82, -82 }; const short AgentParser::yydefgoto_[] = { -1, 4, 5, 6, 7, 23, 27, 16, 17, 18, - 25, 93, 32, 33, 19, 24, 29, 30, 195, 21, + 25, 93, 32, 33, 19, 24, 29, 30, 198, 21, 26, 35, 36, 37, 63, 48, 49, 50, 65, 51, - 196, 67, 197, 68, 54, 71, 119, 120, 121, 136, - 153, 154, 155, 179, 156, 180, 55, 96, 113, 114, - 115, 131, 116, 132, 117, 133, 198, 199, 200, 215, - 201, 216, 248, 56, 69, 104, 105, 106, 126, 173, - 107, 127, 108, 128, 190, 191, 192, 212, 231, 232, - 233, 242, 234, 243, 57, 72, 123, 124, 139, 165, - 166, 167, 183, 168, 169, 186, 170, 184, 240, 241, - 249, 260, 261, 262, 270, 263, 264, 265, 266, 274 + 199, 67, 200, 68, 54, 71, 122, 123, 124, 139, + 156, 157, 158, 182, 159, 183, 55, 96, 116, 117, + 118, 134, 119, 135, 120, 136, 201, 202, 203, 218, + 204, 219, 251, 56, 69, 107, 108, 109, 129, 176, + 110, 130, 111, 131, 193, 194, 195, 215, 234, 235, + 236, 245, 237, 246, 57, 72, 126, 127, 142, 168, + 169, 170, 186, 171, 172, 189, 173, 187, 243, 244, + 252, 263, 264, 265, 273, 266, 267, 268, 269, 277 }; const short AgentParser::yytable_[] = { - 47, 52, 53, 92, 74, 28, 40, 41, 8, 75, - 9, 31, 10, 20, 11, 109, 110, 111, 150, 151, - 22, 38, 39, 40, 41, 42, 158, 159, 34, 160, - 161, 74, 43, 46, 150, 151, 125, 46, 46, 44, - 76, 77, 45, 40, 41, 202, 203, 47, 52, 53, - 12, 13, 14, 15, 58, 46, 193, 194, 140, 40, - 41, 141, 60, 47, 52, 53, 226, 227, 255, 112, - 99, 256, 257, 258, 259, 46, 129, 134, 181, 187, - 217, 130, 135, 182, 188, 218, 59, 217, 217, 244, - 275, 46, 219, 220, 245, 276, 101, 250, 102, 103, - 251, 1, 2, 3, 61, 62, 64, 112, 66, 152, - 70, 73, 162, 163, 164, 78, 79, 80, 81, 82, - 83, 84, 172, 86, 87, 85, 92, 89, 90, 10, - 97, 95, 98, 91, 94, 118, 122, 137, 138, 175, - 142, 143, 144, 146, 147, 148, 174, 278, 214, 176, - 177, 178, 185, 189, 204, 205, 207, 208, 210, 221, - 162, 163, 164, 213, 224, 236, 237, 239, 252, 253, - 271, 272, 209, 273, 277, 223, 281, 225, 246, 157, - 100, 222, 88, 247, 206, 228, 229, 230, 149, 238, - 145, 235, 268, 254, 269, 267, 171, 282, 211, 0, - 0, 0, 279, 0, 280, 0, 0, 0, 283, 0, - 0, 0, 0, 284, 0, 0, 0, 228, 229, 230 + 47, 92, 52, 53, 8, 74, 20, 28, 40, 41, + 75, 9, 22, 10, 31, 11, 40, 41, 34, 101, + 58, 102, 103, 38, 39, 40, 41, 42, 161, 162, + 74, 163, 164, 258, 43, 128, 259, 260, 261, 262, + 46, 44, 76, 77, 45, 40, 41, 47, 46, 52, + 53, 12, 13, 14, 15, 132, 59, 46, 196, 197, + 133, 153, 154, 47, 61, 52, 53, 60, 104, 115, + 105, 106, 99, 62, 40, 41, 46, 46, 112, 113, + 114, 229, 230, 137, 184, 190, 220, 220, 138, 185, + 191, 221, 222, 220, 247, 64, 278, 81, 223, 248, + 46, 279, 1, 2, 3, 104, 46, 105, 106, 66, + 115, 143, 155, 253, 144, 165, 254, 166, 167, 153, + 154, 205, 206, 70, 73, 79, 80, 92, 82, 83, + 78, 84, 86, 85, 87, 89, 90, 91, 97, 10, + 94, 95, 98, 121, 141, 125, 140, 145, 146, 147, + 149, 150, 151, 188, 177, 178, 175, 212, 179, 180, + 181, 192, 207, 165, 208, 166, 167, 210, 211, 213, + 217, 281, 216, 227, 239, 240, 242, 255, 256, 274, + 224, 275, 276, 280, 284, 250, 225, 226, 231, 100, + 232, 233, 88, 209, 152, 160, 148, 241, 238, 257, + 228, 249, 174, 214, 271, 285, 272, 270, 282, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 283, 0, + 231, 286, 232, 233, 0, 0, 287 }; const short AgentParser::yycheck_[] = { - 27, 27, 27, 82, 3, 24, 13, 14, 0, 8, - 5, 45, 7, 7, 9, 23, 24, 25, 30, 31, - 7, 11, 12, 13, 14, 15, 33, 34, 10, 36, - 37, 3, 22, 45, 30, 31, 8, 45, 45, 29, - 59, 60, 32, 13, 14, 177, 178, 74, 74, 74, - 45, 46, 47, 48, 6, 45, 26, 27, 3, 13, - 14, 6, 4, 90, 90, 90, 20, 21, 35, 96, - 89, 38, 39, 40, 41, 45, 3, 3, 3, 3, - 3, 8, 8, 8, 8, 8, 3, 3, 3, 3, - 3, 45, 8, 8, 8, 8, 16, 3, 18, 19, - 6, 42, 43, 44, 8, 3, 8, 134, 4, 136, - 4, 4, 139, 139, 139, 45, 4, 4, 46, 4, - 4, 4, 17, 4, 4, 7, 205, 4, 7, 7, - 5, 7, 5, 45, 45, 7, 7, 6, 3, 5, - 4, 4, 4, 4, 4, 4, 45, 48, 3, 7, - 7, 7, 4, 7, 4, 4, 4, 4, 4, 45, - 187, 187, 187, 6, 5, 4, 4, 7, 4, 4, - 4, 4, 46, 4, 4, 45, 4, 45, 45, 138, - 90, 205, 74, 28, 181, 212, 212, 212, 134, 217, - 129, 214, 45, 244, 45, 250, 140, 275, 187, -1, - -1, -1, 46, -1, 46, -1, -1, -1, 45, -1, - -1, -1, -1, 45, -1, -1, -1, 244, 244, 244 + 27, 82, 27, 27, 0, 3, 7, 24, 13, 14, + 8, 5, 7, 7, 45, 9, 13, 14, 10, 16, + 6, 18, 19, 11, 12, 13, 14, 15, 33, 34, + 3, 36, 37, 35, 22, 8, 38, 39, 40, 41, + 45, 29, 59, 60, 32, 13, 14, 74, 45, 74, + 74, 45, 46, 47, 48, 3, 3, 45, 26, 27, + 8, 30, 31, 90, 8, 90, 90, 4, 95, 96, + 95, 95, 89, 3, 13, 14, 45, 45, 23, 24, + 25, 20, 21, 3, 3, 3, 3, 3, 8, 8, + 8, 8, 8, 3, 3, 8, 3, 46, 8, 8, + 45, 8, 42, 43, 44, 132, 45, 132, 132, 4, + 137, 3, 139, 3, 6, 142, 6, 142, 142, 30, + 31, 180, 181, 4, 4, 4, 4, 208, 4, 4, + 45, 4, 4, 7, 4, 4, 7, 45, 5, 7, + 45, 7, 5, 7, 3, 7, 6, 4, 4, 4, + 4, 4, 4, 4, 45, 5, 17, 46, 7, 7, + 7, 7, 4, 190, 4, 190, 190, 4, 4, 4, + 3, 48, 6, 5, 4, 4, 7, 4, 4, 4, + 45, 4, 4, 4, 4, 28, 208, 45, 215, 90, + 215, 215, 74, 184, 137, 141, 132, 220, 217, 247, + 45, 45, 143, 190, 45, 278, 45, 253, 46, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 46, -1, + 247, 45, 247, 247, -1, -1, 45 }; const unsigned char @@ -2064,25 +2066,25 @@ namespace isc { namespace agent { 4, 84, 134, 4, 3, 8, 57, 57, 45, 4, 4, 46, 4, 4, 4, 7, 4, 4, 75, 4, 7, 45, 58, 60, 45, 7, 96, 5, 5, 57, - 74, 16, 18, 19, 114, 115, 116, 119, 121, 23, - 24, 25, 67, 97, 98, 99, 101, 103, 7, 85, - 86, 87, 7, 135, 136, 8, 117, 120, 122, 3, - 8, 100, 102, 104, 3, 8, 88, 6, 3, 137, - 3, 6, 4, 4, 4, 115, 4, 4, 4, 98, - 30, 31, 67, 89, 90, 91, 93, 87, 33, 34, - 36, 37, 67, 79, 81, 138, 139, 140, 142, 143, - 145, 136, 17, 118, 45, 5, 7, 7, 7, 92, - 94, 3, 8, 141, 146, 4, 144, 3, 8, 7, - 123, 124, 125, 26, 27, 67, 79, 81, 105, 106, - 107, 109, 105, 105, 4, 4, 90, 4, 4, 46, - 4, 139, 126, 6, 3, 108, 110, 3, 8, 8, - 8, 45, 60, 45, 5, 45, 20, 21, 67, 79, - 81, 127, 128, 129, 131, 125, 4, 4, 106, 7, - 147, 148, 130, 132, 3, 8, 45, 28, 111, 149, - 3, 6, 4, 4, 128, 35, 38, 39, 40, 41, - 150, 151, 152, 154, 155, 156, 157, 148, 45, 45, - 153, 4, 4, 4, 158, 3, 8, 4, 48, 46, - 46, 4, 151, 45, 45 + 74, 16, 18, 19, 67, 79, 81, 114, 115, 116, + 119, 121, 23, 24, 25, 67, 97, 98, 99, 101, + 103, 7, 85, 86, 87, 7, 135, 136, 8, 117, + 120, 122, 3, 8, 100, 102, 104, 3, 8, 88, + 6, 3, 137, 3, 6, 4, 4, 4, 115, 4, + 4, 4, 98, 30, 31, 67, 89, 90, 91, 93, + 87, 33, 34, 36, 37, 67, 79, 81, 138, 139, + 140, 142, 143, 145, 136, 17, 118, 45, 5, 7, + 7, 7, 92, 94, 3, 8, 141, 146, 4, 144, + 3, 8, 7, 123, 124, 125, 26, 27, 67, 79, + 81, 105, 106, 107, 109, 105, 105, 4, 4, 90, + 4, 4, 46, 4, 139, 126, 6, 3, 108, 110, + 3, 8, 8, 8, 45, 60, 45, 5, 45, 20, + 21, 67, 79, 81, 127, 128, 129, 131, 125, 4, + 4, 106, 7, 147, 148, 130, 132, 3, 8, 45, + 28, 111, 149, 3, 6, 4, 4, 128, 35, 38, + 39, 40, 41, 150, 151, 152, 154, 155, 156, 157, + 148, 45, 45, 153, 4, 4, 4, 158, 3, 8, + 4, 48, 46, 46, 4, 151, 45, 45 }; const unsigned char @@ -2098,13 +2100,14 @@ namespace isc { namespace agent { 91, 94, 93, 96, 95, 97, 97, 98, 98, 98, 98, 100, 99, 102, 101, 104, 103, 105, 105, 106, 106, 106, 106, 106, 108, 107, 110, 109, 111, 113, - 112, 114, 114, 115, 115, 115, 117, 116, 118, 120, - 119, 122, 121, 123, 123, 124, 124, 126, 125, 127, - 127, 128, 128, 128, 128, 128, 130, 129, 132, 131, - 134, 133, 135, 135, 137, 136, 138, 138, 139, 139, - 139, 139, 139, 139, 139, 141, 140, 142, 144, 143, - 146, 145, 147, 147, 149, 148, 150, 150, 151, 151, - 151, 151, 151, 153, 152, 154, 155, 156, 158, 157 + 112, 114, 114, 115, 115, 115, 115, 115, 115, 117, + 116, 118, 120, 119, 122, 121, 123, 123, 124, 124, + 126, 125, 127, 127, 128, 128, 128, 128, 128, 130, + 129, 132, 131, 134, 133, 135, 135, 137, 136, 138, + 138, 139, 139, 139, 139, 139, 139, 139, 141, 140, + 142, 144, 143, 146, 145, 147, 147, 149, 148, 150, + 150, 151, 151, 151, 151, 151, 153, 152, 154, 155, + 156, 158, 157 }; const signed char @@ -2120,13 +2123,14 @@ namespace isc { namespace agent { 4, 0, 4, 0, 6, 1, 3, 1, 1, 1, 1, 0, 6, 0, 6, 0, 6, 1, 3, 1, 1, 1, 1, 1, 0, 4, 0, 4, 1, 0, - 6, 1, 3, 1, 1, 1, 0, 4, 1, 0, - 4, 0, 6, 0, 1, 1, 3, 0, 4, 1, - 3, 1, 1, 1, 1, 1, 0, 4, 0, 4, - 0, 6, 1, 3, 0, 4, 1, 3, 1, 1, - 1, 1, 1, 1, 1, 0, 4, 3, 0, 4, - 0, 6, 1, 3, 0, 4, 1, 3, 1, 1, - 1, 1, 1, 0, 4, 3, 3, 3, 0, 4 + 6, 1, 3, 1, 1, 1, 1, 1, 1, 0, + 4, 1, 0, 4, 0, 6, 0, 1, 1, 3, + 0, 4, 1, 3, 1, 1, 1, 1, 1, 0, + 4, 0, 4, 0, 6, 1, 3, 0, 4, 1, + 3, 1, 1, 1, 1, 1, 1, 1, 0, 4, + 3, 0, 4, 0, 6, 1, 3, 0, 4, 1, + 3, 1, 1, 1, 1, 1, 0, 4, 3, 3, + 3, 0, 4 }; @@ -2188,13 +2192,14 @@ namespace isc { namespace agent { 382, 390, 390, 400, 400, 413, 414, 419, 420, 421, 422, 426, 426, 437, 437, 448, 448, 459, 460, 464, 465, 466, 467, 468, 472, 472, 481, 481, 489, 496, - 496, 509, 510, 513, 514, 515, 518, 518, 526, 529, - 529, 538, 538, 549, 550, 553, 554, 557, 557, 565, - 566, 569, 570, 571, 572, 573, 576, 576, 584, 584, - 596, 596, 608, 609, 613, 613, 621, 622, 625, 626, - 627, 628, 629, 630, 631, 634, 634, 642, 647, 647, - 655, 655, 665, 666, 669, 669, 677, 678, 681, 682, - 683, 684, 685, 688, 688, 696, 701, 706, 711, 711 + 496, 509, 510, 513, 514, 515, 516, 517, 518, 521, + 521, 529, 532, 532, 541, 541, 552, 553, 556, 557, + 560, 560, 568, 569, 572, 573, 574, 575, 576, 579, + 579, 587, 587, 599, 599, 611, 612, 616, 616, 624, + 625, 628, 629, 630, 631, 632, 633, 634, 637, 637, + 645, 650, 650, 658, 658, 668, 669, 672, 672, 680, + 681, 684, 685, 686, 687, 688, 691, 691, 699, 704, + 709, 714, 714 }; void @@ -2227,9 +2232,9 @@ namespace isc { namespace agent { #line 14 "agent_parser.yy" } } // isc::agent -#line 2231 "agent_parser.cc" +#line 2236 "agent_parser.cc" -#line 719 "agent_parser.yy" +#line 722 "agent_parser.yy" void diff --git a/src/bin/agent/agent_parser.h b/src/bin/agent/agent_parser.h index 074d7fa5d5..dcc408e81d 100644 --- a/src/bin/agent/agent_parser.h +++ b/src/bin/agent/agent_parser.h @@ -1882,7 +1882,7 @@ switch (yykind) /// \param yyvalue the value to check static bool yy_table_value_is_error_ (int yyvalue); - static const short yypact_ninf_; + static const signed char yypact_ninf_; static const signed char yytable_ninf_; /// Convert a scanner token kind \a t to a symbol kind. @@ -1908,7 +1908,7 @@ switch (yykind) static const unsigned char yydefact_[]; // YYPGOTO[NTERM-NUM]. - static const short yypgoto_[]; + static const signed char yypgoto_[]; // YYDEFGOTO[NTERM-NUM]. static const short yydefgoto_[]; @@ -2160,7 +2160,7 @@ switch (yykind) /// Constants. enum { - yylast_ = 219, ///< Last index in yytable_. + yylast_ = 226, ///< Last index in yytable_. yynnts_ = 110, ///< Number of nonterminal symbols. yyfinal_ = 8 ///< Termination state number. }; diff --git a/src/bin/agent/location.hh b/src/bin/agent/location.hh index 8d99d97acb..f46a19682a 100644 --- a/src/bin/agent/location.hh +++ b/src/bin/agent/location.hh @@ -1,4 +1,4 @@ -// Generated 202009121616 +// Generated 202009132003 // A Bison parser, made by GNU Bison 3.7.2. // Locations for Bison parsers in C++ diff --git a/src/bin/agent/position.hh b/src/bin/agent/position.hh index b9faa8db69..62bce2b799 100644 --- a/src/bin/agent/position.hh +++ b/src/bin/agent/position.hh @@ -1,4 +1,4 @@ -// Generated 202009121616 +// Generated 202009132003 // A Bison parser, made by GNU Bison 3.7.2. // Starting with Bison 3.2, this file is useless: the structure it diff --git a/src/bin/agent/stack.hh b/src/bin/agent/stack.hh index 430d2020d9..48f2900a33 100644 --- a/src/bin/agent/stack.hh +++ b/src/bin/agent/stack.hh @@ -1,4 +1,4 @@ -// Generated 202009121616 +// Generated 202009132003 // A Bison parser, made by GNU Bison 3.7.2. // Starting with Bison 3.2, this file is useless: the structure it -- GitLab From 7782e49dadab5e14dd3c2c216da492d95c55db0c Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Sun, 13 Sep 2020 22:05:30 +0200 Subject: [PATCH 27/33] [#1304] Checkpoint before regen (2) --- src/bin/agent/agent_lexer.ll | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bin/agent/agent_lexer.ll b/src/bin/agent/agent_lexer.ll index 37d3df9fda..6c9d390eab 100644 --- a/src/bin/agent/agent_lexer.ll +++ b/src/bin/agent/agent_lexer.ll @@ -203,7 +203,7 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence} \"user-context\" { switch(driver.ctx_) { case ParserContext::AGENT: - case ParserContext::AUTHENTICATION; + case ParserContext::AUTHENTICATION: case ParserContext::CLIENTS: case ParserContext::SERVER: case ParserContext::LOGGERS: @@ -216,7 +216,7 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence} \"comment\" { switch(driver.ctx_) { case ParserContext::AGENT: - case ParserContext::AUTHENTICATION; + case ParserContext::AUTHENTICATION: case ParserContext::CLIENTS: case ParserContext::SERVER: case ParserContext::LOGGERS: -- GitLab From 0c9d92c927aa42419554335c2bffa82e993e1692 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Sun, 13 Sep 2020 20:05:04 +0000 Subject: [PATCH 28/33] [#1304] regen files --- src/bin/agent/agent_lexer.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bin/agent/agent_lexer.cc b/src/bin/agent/agent_lexer.cc index da5db397fe..904e64d855 100644 --- a/src/bin/agent/agent_lexer.cc +++ b/src/bin/agent/agent_lexer.cc @@ -2016,7 +2016,7 @@ YY_RULE_SETUP { switch(driver.ctx_) { case ParserContext::AGENT: - case ParserContext::AUTHENTICATION; + case ParserContext::AUTHENTICATION: case ParserContext::CLIENTS: case ParserContext::SERVER: case ParserContext::LOGGERS: @@ -2032,7 +2032,7 @@ YY_RULE_SETUP { switch(driver.ctx_) { case ParserContext::AGENT: - case ParserContext::AUTHENTICATION; + case ParserContext::AUTHENTICATION: case ParserContext::CLIENTS: case ParserContext::SERVER: case ParserContext::LOGGERS: -- GitLab From c353ecbedaa54173b1e4bd1ee3932f1e22ecd780 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Sun, 13 Sep 2020 22:21:33 +0200 Subject: [PATCH 29/33] [#1304] Checkpoint before regen (3) --- doc/examples/agent/comments.json | 2 ++ src/bin/agent/agent_lexer.ll | 2 +- src/bin/agent/simple_parser.cc | 2 +- src/bin/agent/tests/testdata/get_config.json | 21 +++++++++++--------- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/doc/examples/agent/comments.json b/doc/examples/agent/comments.json index 01eb15bb25..39f3ff0ce2 100644 --- a/doc/examples/agent/comments.json +++ b/doc/examples/agent/comments.json @@ -16,6 +16,8 @@ { "comment": "basic HTTP authentication", + "type": "basic", + // In basic HTTP authentication clients "clients": [ diff --git a/src/bin/agent/agent_lexer.ll b/src/bin/agent/agent_lexer.ll index 6c9d390eab..bdb4f88878 100644 --- a/src/bin/agent/agent_lexer.ll +++ b/src/bin/agent/agent_lexer.ll @@ -258,7 +258,7 @@ ControlCharacterFill [^"\\]|\\{JSONEscapeSequence} case ParserContext::AUTHENTICATION: return AgentParser::make_REALM(driver.loc_); default: - return AgentParser::make_STRING("authentication", driver.loc_); + return AgentParser::make_STRING("realm", driver.loc_); } } diff --git a/src/bin/agent/simple_parser.cc b/src/bin/agent/simple_parser.cc index 1890608d33..eb65352f85 100644 --- a/src/bin/agent/simple_parser.cc +++ b/src/bin/agent/simple_parser.cc @@ -115,7 +115,7 @@ AgentSimpleParser::parse(const CtrlAgentCfgContextPtr& ctx, } // Basic HTTP authentications are third. - ConstElementPtr auth_config = config->get("authentications"); + ConstElementPtr auth_config = config->get("authentication"); if (auth_config) { using namespace isc::http; BasicHttpAuthConfigPtr auth(new BasicHttpAuthConfig()); diff --git a/src/bin/agent/tests/testdata/get_config.json b/src/bin/agent/tests/testdata/get_config.json index db6515f03c..f60c521a53 100644 --- a/src/bin/agent/tests/testdata/get_config.json +++ b/src/bin/agent/tests/testdata/get_config.json @@ -1,15 +1,18 @@ { "Control-agent": { - "basic-authentication-realm": "kea-control-agent", - "basic-authentications": [ - { - "password": "1234", - "user": "admin", - "user-context": { - "comment": "admin is authorized" + "authentication": { + "clients": [ + { + "password": "1234", + "user": "admin", + "user-context": { + "comment": "admin is authorized" + } } - } - ], + ], + "realm": "kea-control-agent", + "type": "basic" + }, "control-sockets": { "d2": { "socket-name": "/tmp/kea-ddns-ctrl-socket", -- GitLab From 90fad75934837e0ac10fc0637320383baf162d4b Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Sun, 13 Sep 2020 20:21:03 +0000 Subject: [PATCH 30/33] [#1304] regen files --- src/bin/agent/agent_lexer.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/agent/agent_lexer.cc b/src/bin/agent/agent_lexer.cc index 904e64d855..0462e93fbb 100644 --- a/src/bin/agent/agent_lexer.cc +++ b/src/bin/agent/agent_lexer.cc @@ -2086,7 +2086,7 @@ YY_RULE_SETUP case ParserContext::AUTHENTICATION: return AgentParser::make_REALM(driver.loc_); default: - return AgentParser::make_STRING("authentication", driver.loc_); + return AgentParser::make_STRING("realm", driver.loc_); } } YY_BREAK -- GitLab From 20e8d1a7b4a456d2bcc721d5376f1a605084394d Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Sun, 13 Sep 2020 22:33:30 +0200 Subject: [PATCH 31/33] [#1304] Updated shell tests --- src/bin/shell/tests/basic_auth_tests.sh.in | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/bin/shell/tests/basic_auth_tests.sh.in b/src/bin/shell/tests/basic_auth_tests.sh.in index 57fb3ad438..cdb0dba65d 100644 --- a/src/bin/shell/tests/basic_auth_tests.sh.in +++ b/src/bin/shell/tests/basic_auth_tests.sh.in @@ -16,13 +16,17 @@ CONFIG="{ { \"http-host\": \"127.0.0.1\", \"http-port\": 8081, - \"basic-authentication-realm\": \"ISC.ORG\", - \"basic-authentications\": [ + \"authentication\": { - \"user\": \"pet\", - \"password\": \"meow\" - } - ], + \"type\": \"basic\", + \"realm\": \"ISC.ORG\", + \"clients\": [ + { + \"user\": \"pet\", + \"password\": \"meow\" + } + ] + }, \"loggers\": [ { \"name\": \"kea-ctrl-agent\", -- GitLab From 5d3b18f80ee3906624e2bbff61526ddb5d502809 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Mon, 14 Sep 2020 14:19:55 +0200 Subject: [PATCH 32/33] [#1304] Addressed comments --- doc/sphinx/arm/hooks-ha.rst | 2 +- doc/sphinx/arm/shell.rst | 4 ++-- src/lib/http/basic_auth_config.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/sphinx/arm/hooks-ha.rst b/doc/sphinx/arm/hooks-ha.rst index 13967b8550..6663acc990 100644 --- a/doc/sphinx/arm/hooks-ha.rst +++ b/doc/sphinx/arm/hooks-ha.rst @@ -594,7 +594,7 @@ list: commands to that server. - ``basic-auth-user`` - specifies the user id for basic HTTP - authentication. If not specified or specified to the empty string + authentication. If not specified or specified as an empty string no authentication header will be added to HTTP transactions. Must not contain the colon (:) character. diff --git a/doc/sphinx/arm/shell.rst b/doc/sphinx/arm/shell.rst index 39675c048d..5871079766 100644 --- a/doc/sphinx/arm/shell.rst +++ b/doc/sphinx/arm/shell.rst @@ -130,5 +130,5 @@ tool. .. note:: - When using this tool with basic HTTP authentication please not forget - that command line arguments are not hidden to local users. + When using this tool with basic HTTP authentication please keep in + mind that command line arguments are not hidden to local users. diff --git a/src/lib/http/basic_auth_config.h b/src/lib/http/basic_auth_config.h index 78d541061b..ec88e12ff1 100644 --- a/src/lib/http/basic_auth_config.h +++ b/src/lib/http/basic_auth_config.h @@ -16,7 +16,7 @@ namespace isc { namespace http { /// @brief Type of basic HTTP authentication credential and user id map, -/// e.g. map["am9obmRvZTpzZWNyZXQx" = "johndoe". +/// e.g. map["am9obmRvZTpzZWNyZXQx"] = "johndoe". /// /// The map is used to verify a received credential: if it is not in it /// the authentication fails, if it is in it the user id is logged. -- GitLab From f3074c98f946b719361585d6de2a699695a57a4d Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Mon, 14 Sep 2020 15:32:51 +0200 Subject: [PATCH 33/33] [#1304] Added ChangeLog entry --- ChangeLog | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ChangeLog b/ChangeLog index 3a1dd1658b..9e3030a5f5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +1800. [func] fdupont + Added support of basic HTTP authentication in HTTP library, + control agent, kea shell and high availability hook. + (Gitlab #1304) + 1799. [bug] fdupont Checked execution of queries to get schema versions of MySQL and PostgreSQL database in kea-admin. -- GitLab